From b08a63790c0fbeacb3f96a74e3eb15abe8c70dab Mon Sep 17 00:00:00 2001
From: Piotr Dziwinski <piotrdz@gmail.com>
Date: Mon, 25 Jun 2012 19:59:17 +0200
Subject: [PATCH] SDL project

- added (very basic) SDL template in CApplication and CEngine
- split project into two targets: colobot_old (dependent on DirectX and WinAPI)
  and colobot_new (dependent on SDL and OpenGL)
- moved sound.h/cpp to old/ and created new template in Snd namespace
- added platform-independent dialog boxes in app/system.h/cpp
---
 CMakeLists.txt                  |   11 +-
 src/CMakeLists.txt              |  192 +++-
 src/app/app.cpp                 |  504 +++++++++-
 src/app/app.h                   |  111 +--
 src/app/main.cpp                |   41 +
 src/app/system.cpp              |  253 +++++
 src/app/system.h                |   57 ++
 src/common/config.h.cmake       |    8 +
 src/common/event.cpp            |   19 +-
 src/common/event.h              |    4 +-
 src/common/iman.cpp             |    1 -
 src/common/restext.h            |    6 +-
 src/common/struct.h             |    2 -
 src/graphics/common/camera.h    |    1 -
 src/graphics/common/cloud.h     |    2 +-
 src/graphics/common/device.cpp  |   14 +
 src/graphics/common/device.h    |   22 +
 src/graphics/common/engine.cpp  |   50 +
 src/graphics/common/lightning.h |    4 +-
 src/graphics/common/model.h     |    1 -
 src/graphics/common/particle.h  |    2 +-
 src/graphics/common/planet.h    |    1 -
 src/graphics/common/pyro.h      |    8 +-
 src/object/brain.cpp            |    2 +-
 src/object/object.cpp           |    2 +-
 src/object/object.h             |    2 +-
 src/object/robotmain.cpp        |    2 +-
 src/old/blitz.cpp               |    2 +-
 src/old/d3dapp.cpp              |    2 +-
 src/old/d3dengine.cpp           |    2 +-
 src/old/particule.cpp           |    2 +-
 src/old/particule.h             |    2 +-
 src/old/pyro.cpp                |    2 +-
 src/old/sound.cpp               | 1659 +++++++++++++++++++++++++++++++
 src/old/sound.h                 |  242 +++++
 src/old/water.cpp               |    2 +-
 src/physics/physics.cpp         |    2 +-
 src/sound/sound.cpp             | 1659 -------------------------------
 src/sound/sound.h               |  407 +++-----
 src/ui/control.cpp              |    2 +-
 src/ui/displaytext.cpp          |    2 +-
 src/ui/key.cpp                  |    2 +-
 src/ui/maindialog.cpp           |    2 +-
 src/ui/studio.cpp               |    2 +-
 44 files changed, 3284 insertions(+), 2031 deletions(-)
 create mode 100644 src/app/main.cpp
 create mode 100644 src/app/system.cpp
 create mode 100644 src/app/system.h
 create mode 100644 src/common/config.h.cmake
 create mode 100644 src/graphics/common/device.cpp
 create mode 100644 src/old/sound.cpp
 create mode 100644 src/old/sound.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 02016af6..ae0231d1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,9 +1,15 @@
-# CMake project file for compiling with MinGW
+# CMake project file for compiling with GCC/MinGW
 
 cmake_minimum_required(VERSION 2.8)
 
-project(colobot CXX)
+project(colobot C CXX)
 
+# Required packages
+find_package(OpenGL REQUIRED)
+find_package(SDL REQUIRED)
+find_package(SDL_image REQUIRED)
+
+# Build with debugging symbols
 set(CMAKE_BUILD_TYPE debug)
 
 # Currently compiles only with -fpermissive
@@ -11,4 +17,5 @@ set(CMAKE_BUILD_TYPE debug)
 set(CMAKE_CXX_FLAGS_RELEASE "-fpermissive -O2")
 set(CMAKE_CXX_FLAGS_DEBUG "-fpermissive -w -g -O0")
 
+# Subdirectory with sources
 add_subdirectory(src bin)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 024489d6..3f5e2387 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,9 @@
-# CBot shared library
+# CBot shared library is built separately
 add_subdirectory(CBot)
 
-set(SOURCES
+
+# Source files for old target (dependent on WinAPI & DirectX)
+set(OLD_SOURCES
 old/d3dapp.cpp
 old/joystick.cpp
 old/blitz.cpp
@@ -23,29 +25,13 @@ old/d3dutil.cpp
 old/d3dmath.cpp
 old/math3d.cpp
 old/modfile.cpp
-app/app.cpp
+old/sound.cpp
 common/event.cpp
 common/iman.cpp
 common/metafile.cpp
 common/misc.cpp
 common/profile.cpp
 common/restext.cpp
-graphics/common/camera.cpp
-graphics/common/cloud.cpp
-graphics/common/color.cpp
-graphics/common/engine.cpp
-graphics/common/light.cpp
-graphics/common/lightning.cpp
-graphics/common/model.cpp
-graphics/common/modfile.cpp
-graphics/common/particle.cpp
-graphics/common/planet.cpp
-graphics/common/pyro.cpp
-graphics/common/terrain.cpp
-graphics/common/text.cpp
-graphics/common/water.cpp
-graphics/opengl/gldevice.cpp
-graphics/opengl/glengine.cpp
 object/auto/auto.cpp
 object/auto/autobase.cpp
 object/auto/autoconvert.cpp
@@ -110,7 +96,6 @@ physics/physics.cpp
 script/cbottoken.cpp
 script/cmdtoken.cpp
 script/script.cpp
-sound/sound.cpp
 ui/button.cpp
 ui/check.cpp
 ui/color.cpp
@@ -139,25 +124,174 @@ ui/target.cpp
 ui/window.cpp
 )
 
-add_definitions(-DSTRICT -DD3D_OVERLOADS)
+# Source files for new target (dependent on SDL & OpenGL)
+# Commented out files are still dependent on DirectX or WinAPI
+set(NEW_SOURCES
+app/app.cpp
+app/main.cpp
+app/system.cpp
+common/event.cpp
+common/iman.cpp
+# common/metafile.cpp
+# common/misc.cpp
+# common/modfile.cpp
+# common/profile.cpp
+# common/restext.cpp
+graphics/common/camera.cpp
+graphics/common/cloud.cpp
+graphics/common/color.cpp
+graphics/common/device.cpp
+graphics/common/engine.cpp
+graphics/common/light.cpp
+graphics/common/lightning.cpp
+graphics/common/model.cpp
+graphics/common/modfile.cpp
+graphics/common/particle.cpp
+graphics/common/planet.cpp
+graphics/common/pyro.cpp
+graphics/common/terrain.cpp
+graphics/common/text.cpp
+graphics/common/water.cpp
+graphics/opengl/gldevice.cpp
+graphics/opengl/glengine.cpp
+# object/auto/auto.cpp
+# object/auto/autobase.cpp
+# object/auto/autoconvert.cpp
+# object/auto/autoderrick.cpp
+# object/auto/autodestroyer.cpp
+# object/auto/autoegg.cpp
+# object/auto/autoenergy.cpp
+# object/auto/autofactory.cpp
+# object/auto/autoflag.cpp
+# object/auto/autohuston.cpp
+# object/auto/autoinfo.cpp
+# object/auto/autojostle.cpp
+# object/auto/autokid.cpp
+# object/auto/autolabo.cpp
+# object/auto/automush.cpp
+# object/auto/autonest.cpp
+# object/auto/autonuclear.cpp
+# object/auto/autopara.cpp
+# object/auto/autoportico.cpp
+# object/auto/autoradar.cpp
+# object/auto/autorepair.cpp
+# object/auto/autoresearch.cpp
+# object/auto/autoroot.cpp
+# object/auto/autosafe.cpp
+# object/auto/autostation.cpp
+# object/auto/autotower.cpp
+# object/brain.cpp
+# object/mainmovie.cpp
+# object/motion/motion.cpp
+# object/motion/motionant.cpp
+# object/motion/motionbee.cpp
+# object/motion/motionhuman.cpp
+# object/motion/motionmother.cpp
+# object/motion/motionspider.cpp
+# object/motion/motiontoto.cpp
+# object/motion/motionvehicle.cpp
+# object/motion/motionworm.cpp
+# object/object.cpp
+# object/robotmain.cpp
+# object/task/task.cpp
+# object/task/taskadvance.cpp
+# object/task/taskbuild.cpp
+# object/task/taskfire.cpp
+# object/task/taskfireant.cpp
+# object/task/taskflag.cpp
+# object/task/taskgoto.cpp
+# object/task/taskgungoal.cpp
+# object/task/taskinfo.cpp
+# object/task/taskmanager.cpp
+# object/task/taskmanip.cpp
+# object/task/taskpen.cpp
+# object/task/taskrecover.cpp
+# object/task/taskreset.cpp
+# object/task/tasksearch.cpp
+# object/task/taskshield.cpp
+# object/task/taskspiderexplo.cpp
+# object/task/tasktake.cpp
+# object/task/taskterraform.cpp
+# object/task/taskturn.cpp
+# object/task/taskwait.cpp
+# physics/physics.cpp
+# script/cbottoken.cpp
+# script/cmdtoken.cpp
+# script/script.cpp
+sound/sound.cpp
+# ui/button.cpp
+# ui/check.cpp
+# ui/color.cpp
+# ui/compass.cpp
+# ui/control.cpp
+# ui/displayinfo.cpp
+# ui/displaytext.cpp
+# ui/edit.cpp
+# ui/editvalue.cpp
+# ui/gauge.cpp
+# ui/group.cpp
+# ui/image.cpp
+# ui/interface.cpp
+# ui/key.cpp
+# ui/label.cpp
+# ui/list.cpp
+# ui/maindialog.cpp
+# ui/mainmap.cpp
+# ui/mainshort.cpp
+# ui/map.cpp
+# ui/scroll.cpp
+# ui/shortcut.cpp
+# ui/slider.cpp
+# ui/studio.cpp
+# ui/target.cpp
+# ui/window.cpp
+)
 
 # Change to DirectX SDK directory
 set(DXSDK_DIR "c:/dxsdk")
 
-include_directories(${DXSDK_DIR}/include .)
+# Configure options
+option(DEBUG "Enable debug output" ON)
+
+if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+  set(PLATFORM_WINDOWS 1)
+  set(PLATFORM_LINUX   0)
+  set(PLATFORM_OTHER   0)
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+  set(PLATFORM_WINDOWS 0)
+  set(PLATFORM_LINUX   1)
+  set(PLATFORM_OTHER   0)
+else()
+  set(PLATFORM_WINDOWS 0)
+  set(PLATFORM_LINUX   0)
+  set(PLATFORM_OTHER   1)
+endif()
+
+# Configure file
+configure_file(common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h)
+
+# #defines needed for old target
+add_definitions(-DSTRICT -DD3D_OVERLOADS)
+
+include_directories(${DXSDK_DIR}/include . ${CMAKE_CURRENT_BINARY_DIR})
 
 link_directories(${CMAKE_CURRENT_SOURCE_DIR}/CBot ${DXSDK_DIR}/lib)
 
-set( LIBS -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32
+
+# Old target
+set(OLD_LIBS -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32
     -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32
     -lodbccp32 -lwinmm
-    ${DXSDK_DIR}/lib/ddraw.lib ${DXSDK_DIR}/lib/dinput.lib ${DXSDK_DIR}/lib/dxguid.lib ${DXSDK_DIR}/lib/d3d8.lib ${DXSDK_DIR}/lib/dsound.lib )
+    ${DXSDK_DIR}/lib/ddraw.lib ${DXSDK_DIR}/lib/dinput.lib ${DXSDK_DIR}/lib/dxguid.lib ${DXSDK_DIR}/lib/d3d8.lib ${DXSDK_DIR}/lib/dsound.lib)
 
-# To build with libwine:
-#  include_directories(/usr/include/wine/windows /usr/include/wine/msvcrt)
-#  set(LIBS -lwine)
+add_executable(colobot_old ${OLD_SOURCES})
 
-add_executable(colobot ${SOURCES})
+target_link_libraries(colobot_old CBot ${OLD_LIBS})
 
-target_link_libraries(colobot CBot ${LIBS})
 
+# New target
+set(NEW_LIBS ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} ${OPENGL_LIBRARY})
+
+add_executable(colobot_new ${NEW_SOURCES})
+
+target_link_libraries(colobot_new ${NEW_LIBS})
diff --git a/src/app/app.cpp b/src/app/app.cpp
index 0938f2aa..726d32dc 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -19,5 +19,507 @@
 
 #include "app/app.h"
 
+#include "app/system.h"
+#include "common/iman.h"
 
-// TODO implementation
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+
+
+/**
+ * \struct ApplicationPrivate Private data of CApplication class
+ *
+ * Contains SDL-specific variables that should not be visible outside application module.
+ */
+struct ApplicationPrivate
+{
+	//! Display surface
+	SDL_Surface *surface;
+	//! Currently handled event
+	SDL_Event currentEvent;
+	//! Joystick
+	SDL_Joystick *joystick;
+	//! Index of joystick device
+	int joystickDevice;
+
+	ApplicationPrivate()
+	{
+		memset(&currentEvent, 0, sizeof(SDL_Event));
+		surface = NULL;
+		joystick = NULL;
+		joystickDevice = 0;
+	}
+};
+
+
+CApplication::CApplication()
+{
+	m_private = new ApplicationPrivate();
+	m_exitCode = 0;
+
+	m_iMan = new CInstanceManager();
+	m_event = new CEvent(m_iMan);
+
+	m_engine = 0;
+	m_robotMain = 0;
+	m_sound     = 0;
+
+	m_keyState = 0;
+	m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
+	m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
+
+	m_vidMemTotal  = 0;
+	m_active      = false;
+	m_activateApp = false;
+	m_ready       = false;
+	m_joystick    = false;
+	m_time        = 0.0f;
+
+	for (int i = 0; i < 32; i++)
+	{
+		m_joyButton[i] = false;
+	}
+
+	m_windowTitle  = "COLOBOT";
+
+	m_appUseZBuffer  = true;
+	m_appUseStereo   = true;
+	m_showStats      = false;
+	m_debugMode      = false;
+	m_audioState     = true;
+	m_audioTrack     = true;
+	m_niceMouse      = false;
+	m_setupMode      = true;
+
+	ResetKey();
+}
+
+CApplication::~CApplication()
+{
+	delete m_private;
+	m_private = NULL;
+
+	delete m_iMan;
+	m_iMan = NULL;
+}
+
+Error CApplication::ParseArguments(int argc, char *argv[])
+{
+	for (int i = 1; i < argc; ++i)
+	{
+		std::string arg = argv[i];
+
+		if (arg == "-debug")
+		{
+			m_showStats = true;
+			SetDebugMode(true);
+		}
+		else if (arg == "-audiostate")
+		{
+			m_audioState = false;
+		}
+		else if (arg == "-audiotrack")
+		{
+			m_audioTrack = false;
+		}
+		// TODO else {} report invalid argument
+	}
+
+	return ERR_OK;
+}
+
+bool CApplication::Create()
+{
+/*
+TODO
+	Full screen by default unless in debug mode
+	if (! m_debugMode)
+		m_deviceConfig.fullScreen = true;
+
+	int full = 0;
+	if (GetProfileInt("Device", "FullScreen", full))
+		m_deviceConfig.fullScreen = full == 1;
+*/
+
+	// Temporarily -- only in windowed mode
+	m_deviceConfig.fullScreen = false;
+
+/*
+TODO
+	// Create the 3D engine.
+	m_engine = new CEngine(m_iMan, this);
+
+	// Initialize the app's custom scene stuff
+	if (! m_engine->OneTimeSceneInit())
+	{
+		SystemDialog(SDT_ERROR, "COLOBOT - Error", m_engine->RetError());
+		return false;
+	}
+
+	// Create the sound instance.
+	m_sound = new CSound(m_iMan);
+
+	// Create the robot application.
+	m_robotMain = new CRobotMain(m_iMan);
+*/
+
+
+	Uint32 initFlags = SDL_INIT_VIDEO;
+	if (m_joystick)
+		initFlags |= SDL_INIT_JOYSTICK;
+
+	if (SDL_Init(initFlags) < 0)
+	{
+		SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL initialization error:\n" +  std::string(SDL_GetError()) );
+		return false;
+	}
+
+	const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+	if (! videoInfo)
+	{
+		SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL error while getting video info:\n " + std::string(SDL_GetError()) );
+		return false;
+	}
+
+	Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+
+	if (m_deviceConfig.resizeable)
+		videoFlags |= SDL_RESIZABLE;
+
+	// Use hardware surface if available
+	if (videoInfo->hw_available)
+		videoFlags |= SDL_HWSURFACE;
+	else
+		videoFlags |= SDL_SWSURFACE;
+
+	// Enable hardware blit if available
+	if (videoInfo->blit_hw)
+		videoFlags |= SDL_HWACCEL;
+
+	if (m_deviceConfig.fullScreen)
+		videoFlags |= SDL_FULLSCREEN;
+
+	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+
+	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+	if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0)
+	{
+		SystemDialog( SDT_ERROR, "COLOBOT - Error", std::string("SDL_Image initialization error:\n") +
+													std::string(IMG_GetError()) );
+		return false;
+	}
+
+	m_private->surface = SDL_SetVideoMode(m_deviceConfig.width, m_deviceConfig.height,
+										  m_deviceConfig.bpp, videoFlags);
+
+	if (! m_private->surface)
+	{
+		SystemDialog( SDT_ERROR, "COLOBT - Error", std::string("SDL error while setting video mode:\n") +
+												   std::string(SDL_GetError()) );
+		return false;
+	}
+
+	SDL_WM_SetCaption(m_windowTitle.c_str(), m_windowTitle.c_str());
+
+	SDL_EnableUNICODE(1);
+
+
+/*
+TODO
+
+	InitJoystick();
+
+	if ( !GetProfileInt("Setup", "Sound3D", b3D) )
+	{
+		b3D = true;
+	}
+	m_pSound->SetDebugMode(m_bDebugMode);
+	m_pSound->Create(m_hWnd, b3D);
+	m_pSound->CacheAll();
+	m_pSound->SetState(m_bAudioState);
+	m_pSound->SetAudioTrack(m_bAudioTrack);
+	m_pSound->SetCDpath(m_CDpath);
+
+	// First execution?
+	if ( !GetProfileInt("Setup", "ObjectDirty", iValue) )
+	{
+		m_pD3DEngine->FirstExecuteAdapt(true);
+	}
+
+	// Creates the file colobot.ini at the first execution.
+	m_pRobotMain->CreateIni();
+
+	m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+
+	m_engine->TimeInit();
+*/
+
+	// The app is ready to go
+	m_ready = true;
+
+	return true;
+}
+
+void CApplication::Destroy()
+{
+	if (m_private->joystick != NULL)
+	{
+		SDL_JoystickClose(m_private->joystick);
+		m_private->joystick = NULL;
+	}
+
+	SDL_FreeSurface(m_private->surface);
+	m_private->surface = NULL;
+
+	IMG_Quit();
+
+	SDL_Quit();
+}
+
+int CApplication::Run()
+{
+	m_active = true;
+
+	while (m_private->currentEvent.type != SDL_QUIT)
+	{
+		// Use SDL_PeepEvents() if the app is active, so we can use idle time to
+		// render the scene. Else, use SDL_PollEvent() to avoid eating CPU time.
+		int count = 0;
+		if (m_active)
+		{
+			SDL_PumpEvents();
+			count = SDL_PeepEvents(&m_private->currentEvent, 1, SDL_GETEVENT, SDL_ALLEVENTS);
+		}
+		else
+		{
+			SDL_PollEvent(&m_private->currentEvent);
+		}
+
+		// If received an event
+		if ((m_active && count > 0) || (!m_active))
+		{
+			ParseEvent();
+		}
+
+		// Render a frame during idle time (no messages are waiting)
+		if (m_active && m_ready)
+		{
+			Event event;
+			while (m_event->GetEvent(event))
+			{
+				if (event.event == EVENT_QUIT)
+				{
+					goto end; // exit both loops
+				}
+
+				//m_robotMain->EventProcess(event);
+			}
+
+			//if ( !RetNiceMouse())
+			//{
+			//	SetMouseType(m_engine->RetMouseType());
+			//}
+
+			// If an error occurs, push quit event to the queue
+			if (! Render())
+			{
+				SDL_Event quitEvent;
+				memset(&quitEvent, 0, sizeof(SDL_Event));
+				quitEvent.type = SDL_QUIT;
+				SDL_PushEvent(&quitEvent);
+			}
+		}
+	}
+
+end:
+	//m_sound->StopMusic();
+	Destroy();
+
+	return m_exitCode;
+}
+
+void CApplication::ParseEvent()
+{
+/*	Event event;
+
+	if (m_private->currentEvent.type == SDL_MOUSEBUTTONDOWN)
+	{
+		if (m_private->currentEvent.button.button == SDL_BUTTON_LEFT)
+			event.event = EVENT_LBUTTONDOWN;
+		else if (m_private->currentEvent.button.button == SDL_BUTTON_RIGHT)
+			event.event = EVENT_RBUTTONDOWN;
+	}
+	else if (m_private->currentEvent.type == SDL_MOUSEBUTTONUP)
+	{
+		if (m_private->currentEvent.button.button == SDL_BUTTON_LEFT)
+			event.event = EVENT_LBUTTONUP;
+		else if (m_private->currentEvent.button.button == SDL_BUTTON_RIGHT)
+			event.event = EVENT_RBUTTONUP;
+	}
+	else if (m_private->currentEvent.type == SDL_MOUSEMOTION)
+	{
+		event.event = EVENT_MOUSEMOVE;
+	}
+	else if (m_private->currentEvent.type == SDL_KEYDOWN)
+	{
+		event.event = EVENT_KEYDOWN;
+	}
+	else if (m_private->currentEvent.type == SDL_KEYUP)
+	{
+		event.event = EVENT_KEYUP;
+	}
+
+	if (m_robotMain != NULL && event.event != EVENT_NULL)
+	{
+		m_robotMain->EventProcess(event);
+	}
+	if (m_engine != NULL)
+	{
+		m_engine->MsgProc( hWnd, uMsg, wParam, lParam );
+	}
+
+	ProcessEvent(event);*/
+}
+
+void CApplication::ProcessEvent(Event event)
+{
+	
+}
+
+bool CApplication::Render()
+{
+	bool result = m_engine->Render();
+	if (! result)
+		return false;
+
+	if (m_deviceConfig.doubleBuf)
+		SDL_GL_SwapBuffers();
+
+	return true;
+}
+
+void CApplication::Pause(bool pause)
+{
+	// TODO
+}
+
+void CApplication::SetMousePos(Math::Point pos)
+{
+	// TODO
+}
+
+void CApplication::StepSimulation(float rTime)
+{
+	// TODO
+}
+
+void SetShowStat(bool show)
+{
+	// TODO
+}
+
+bool CApplication::RetShowStat()
+{
+	// TODO
+	return false;
+}
+
+void CApplication::SetDebugMode(bool mode)
+{
+	// TODO
+}
+
+bool CApplication::RetDebugMode()
+{
+	// TODO
+	return false;
+}
+
+bool CApplication::RetSetupMode()
+{
+	// TODO
+	return false;
+}
+
+void CApplication::FlushPressKey()
+{
+	// TODO
+}
+
+void CApplication::ResetKey()
+{
+	// TODO
+}
+
+void CApplication::SetKey(int keyRank, int option, int key)
+{
+	// TODO
+}
+
+int CApplication::RetKey(int keyRank, int option)
+{
+	// TODO
+	return 0;
+}
+
+void CApplication::SetJoystick(bool enable)
+{
+	// TODO
+}
+
+bool CApplication::RetJoystick()
+{
+	// TODO
+	return false;
+}
+
+void SetMouseType(Gfx::MouseType type)
+{
+	// TODO
+}
+
+void SetNiceMouse(bool nice)
+{
+	// TODO
+}
+
+bool CApplication::RetNiceMouse()
+{
+	return false;
+}
+
+bool CApplication::RetNiceMouseCap()
+{
+	return false;
+}
+
+bool CApplication::WriteScreenShot(char *filename, int width, int height)
+{
+	// TODO
+}
+
+void CApplication::InitText()
+{
+	// TODO
+}
+
+void CApplication::DrawSuppl()
+{
+	// TODO
+}
+
+void CApplication::ShowStats()
+{
+	// TODO
+}
+
+void CApplication::OutputText(long x, long y, char* str)
+{
+	// TODO
+}
diff --git a/src/app/app.h b/src/app/app.h
index ee4965d8..ee6184f5 100644
--- a/src/app/app.h
+++ b/src/app/app.h
@@ -21,40 +21,59 @@
 
 
 #include "common/misc.h"
+#include "graphics/common/device.h"
 #include "graphics/common/engine.h"
 
+#include <string>
+
 
 class CInstanceManager;
 class CEvent;
 class CRobotMain;
 class CSound;
 
+struct ApplicationPrivate;
 
+
+/**
+ * \class CApplication Main application
+ *
+ * This class is responsible for creating and handling main application window,
+ * receiving events, etc.
+ *
+ * ...
+ */
 class CApplication
 {
 public:
+	//! Constructor (can only be called once!)
 	CApplication();
+	//! Destructor
 	~CApplication();
 
+public:
+	//! Parses commandline arguments
+	Error		ParseArguments(int argc, char *argv[]);
+	//! Initializes the application
+	bool		Create();
+	//! Main event loop
+	int			Run();
+
 protected:
-	//LRESULT		OnQuerySuspend( DWORD dwFlags );
-	//LRESULT		OnResumeSuspend( DWORD dwData );
+	//! Cleans up before exit
+	void		Destroy();
+	//! Processes an SDL event to Event struct
+	void		ParseEvent();
+	//! Handles some incoming events
+	void		ProcessEvent(Event event);
+	//! Renders the image in window
+	bool		Render();
 
 public:
-	Error		RegQuery();
-	Error		AudioQuery();
-	Error		CheckMistery(char *strCmdLine);
-	int			GetVidMemTotal();
-	bool		IsVideo8MB();
-	bool		IsVideo32MB();
-	//HRESULT		Create( HINSTANCE, TCHAR* );
-	int			Run();
-	//LRESULT		MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
 	void		Pause(bool pause);
-	//Math::Point		ConvPosToInterface(HWND hWnd, LPARAM lParam);
+	void		StepSimulation(float rTime);
+
 	void		SetMousePos(Math::Point pos);
-	void		StepSimul(float rTime);
-	char*		RetCDpath();
 
 	void		SetShowStat(bool show);
 	bool		RetShowStat();
@@ -62,30 +81,21 @@ public:
 	bool		RetDebugMode();
 	bool		RetSetupMode();
 
-	bool		EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
-	bool		RetFullScreen();
-	bool		ChangeDevice(char *device, char *mode, bool bFull);
-
 	void		FlushPressKey();
 	void		ResetKey();
 	void		SetKey(int keyRank, int option, int key);
 	int			RetKey(int keyRank, int option);
 
-	void		SetJoystick(bool bEnable);
+	void		SetJoystick(bool enable);
 	bool		RetJoystick();
 
 	void		SetMouseType(Gfx::MouseType type);
-	void		SetNiceMouse(bool bNice);
+	void		SetNiceMouse(bool nice);
 	bool		RetNiceMouse();
 	bool		RetNiceMouseCap();
 
 	bool		WriteScreenShot(char *filename, int width, int height);
 
-	//bool		GetRenderDC(HDC &hDC);
-	//bool		ReleaseRenderDC(HDC &hDC);
-	//PBITMAPINFO	CreateBitmapInfoStruct(HBITMAP hBmp);
-	//bool		CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
-
 protected:
 	//HRESULT		ConfirmDevice( DDCAPS* pddDriverCaps, D3DDEVICEDESC7* pd3dDeviceDesc );
 	//HRESULT		Initialize3DEnvironment();
@@ -102,55 +112,42 @@ protected:
 	void		OutputText(long x, long y, char* str);
 
 protected:
+	//! Private (SDL-dependent data)
+	ApplicationPrivate*		m_private;
 	CInstanceManager*		m_iMan;
+	Gfx::DeviceConfig		m_deviceConfig;
+	Gfx::CEngine*			m_engine;
 	CEvent*					m_event;
+	CRobotMain*				m_robotMain;
+	CSound*					m_sound;
 
-	//HINSTANCE				m_instance;
-	//HWND					m_hWnd;
-	//D3DEnum_DeviceInfo*		m_pDeviceInfo;
-	//LPDIRECTDRAW7			m_pDD;
-	//LPDIRECT3D7				m_pD3D;
-	//LPDIRECT3DDEVICE7		m_pD3DDevice;
-	//LPDIRECTDRAWSURFACE7	m_pddsRenderTarget;
-	//DDSURFACEDESC2			m_ddsdRenderTarget;
-	//LPDIRECTDRAWSURFACE7	m_pddsDepthBuffer;
+	//! Code to return at exit
+	int 			m_exitCode;
 
-	//HANDLE			m_thread;
-	//DWORD			m_threadId;
-
-	char			m_CDpath[100];
-
-	//CD3DFramework7*	m_pFramework;
 	bool			m_active;
 	bool			m_activateApp;
 	bool			m_ready;
 	bool			m_joystick;
 
+	std::string		m_windowTitle;
 	long			m_vidMemTotal;
-	char*			m_strWindowTitle;
-	bool			m_bAppUseZBuffer;
-	bool			m_bAppUseStereo;
-	bool			m_bShowStats;
-	bool			m_bDebugMode;
-	bool			m_bAudioState;
-	bool			m_bAudioTrack;
-	bool			m_bNiceMouse;
-	bool			m_bSetupMode;
-	//HRESULT			(*m_fnConfirmDevice)(DDCAPS*, D3DDEVICEDESC7*);
-
-public:
-	Gfx::CEngine*	m_pD3DEngine;
-	CRobotMain*		m_pRobotMain;
-	CSound*			m_pSound;
+	bool			m_appUseZBuffer;
+	bool			m_appUseStereo;
+	bool			m_showStats;
+	bool			m_debugMode;
+	bool			m_audioState;
+	bool			m_audioTrack;
+	bool			m_niceMouse;
+	bool			m_setupMode;
 
 	int				m_keyState;
 	Math::Vector	m_axeKey;
 	Math::Vector	m_axeJoy;
 	bool			m_joyButton[32];
 	Math::Point		m_mousePos;
-	long			m_mshMouseWheel;
+	long			m_mouseWheel;
 
-	float			m_aTime;
+	float			m_time;
 	long			m_key[50][2];
 };
 
diff --git a/src/app/main.cpp b/src/app/main.cpp
new file mode 100644
index 00000000..28d21eee
--- /dev/null
+++ b/src/app/main.cpp
@@ -0,0 +1,41 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see  http://www.gnu.org/licenses/.
+
+// main.cpp
+
+#include "app/app.h"
+#include "app/system.h"
+#include "common/misc.h"
+#include "common/restext.h"
+
+
+//! Entry point to the program
+int main(int argc, char *argv[])
+{
+	CApplication app; // single instance of the application
+
+	Error err = app.ParseArguments(argc, argv);
+	if (err != ERR_OK)
+	{
+		SystemDialog(SDT_ERROR, "COLOBOT", "Invalid commandline arguments!\n");
+	}
+
+	if (! app.Create())
+		return 0;
+
+	return app.Run();
+}
diff --git a/src/app/system.cpp b/src/app/system.cpp
new file mode 100644
index 00000000..4f7cd264
--- /dev/null
+++ b/src/app/system.cpp
@@ -0,0 +1,253 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see  http://www.gnu.org/licenses/.
+
+// system.cpp
+
+#include "app/system.h"
+
+#include "common/config.h"
+
+#if defined(PLATFORM_WINDOWS)
+#include <windows.h>
+#elif defined(PLATFORM_LINUX)
+#include <cstdlib>
+#else
+#include <iostream>
+#endif
+
+
+
+SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message);
+SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message);
+SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message);
+
+/**
+ * Displays a system dialog with info, error, question etc. message.
+ *
+ * \param type type of dialog
+ * \param message text of message (in UTF-8)
+ * \param title dialog title (in UTF-8)
+ * \returns result (which button was clicked)
+ */
+SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message)
+{
+	#if defined(PLATFORM_WINDOWS)
+	return SystemDialog_Windows(type, title, message);
+	#elif defined(PLATFORM_LINUX)
+	return SystemDialog_Linux(type, title, message);
+	#else
+	return SystemDialog_Other(type, title, message);
+	#endif
+}
+
+
+
+#if defined(PLATFORM_WINDOWS)
+
+// Convert a wide Unicode string to an UTF8 string
+std::string UTF8_Encode_Windows(const std::wstring &wstr)
+{
+	int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
+	std::string strTo(size_needed, 0);
+	WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
+	return strTo;
+}
+
+// Convert an UTF8 string to a wide Unicode String
+std::wstring UTF8_Decode_Windows(const std::string &str)
+{
+	int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
+	std::wstring wstrTo(size_needed, 0);
+	MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
+	return wstrTo;
+}
+
+SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message)
+{
+	unsigned int windowsType = 0;
+	std::wstring windowsMessage = UTF8_Decode_Windows(message);
+	std::wstring windowsTitle = UTF8_Decode_Windows(title);
+
+	switch (type)
+	{
+		case SDT_INFO:
+		default:
+			windowsType = MB_ICONINFORMATION|MB_OK;
+			break;
+		case SDT_WARNING:
+			windowsType = MB_ICONWARNING|MB_OK;
+			break;
+		case SDT_ERROR:
+			windowsType = MB_ICONERROR|MB_OK;
+			break;
+		case SDT_YES_NO:
+			windowsType = MB_ICONQUESTION|MB_YESNO;
+			break;
+		case SDT_OK_CANCEL:
+			windowsType = MB_ICONWARNING|MB_OKCANCEL;
+			break;
+	}
+
+	switch (MessageBoxW(NULL, windowsMessage.c_str(), windowsTitle.c_str(), windowsType))
+	{
+		case IDOK:
+			return SDR_OK;
+		case IDCANCEL:
+			return SDR_CANCEL;
+		case IDYES:
+			return SDR_YES;
+		case IDNO:
+			return SDR_NO;
+		default:
+			break;
+	}
+
+	return SDR_OK;
+}
+
+#elif defined(PLATFORM_LINUX)
+
+SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message)
+{
+	std::string options = "";
+	switch (type)
+	{
+		case SDT_INFO:
+		default:
+			options = "--info";
+			break;
+        case SDT_WARNING:
+			options = "--warning";
+			break;
+        case SDT_ERROR:
+			options = "--error";
+			break;
+        case SDT_YES_NO:
+			options = "--question --ok-label=\"Yes\" --cancel-label=\"No\"";
+			break;
+        case SDT_OK_CANCEL:
+			options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\"";
+			break;
+	}
+
+	std::string command = "zenity " + options + " --text=\"" + message + "\" --title=\"" + title + "\"";
+	int code = system(command.c_str());
+
+	SystemDialogResult result = SDR_OK;
+	switch (type)
+	{
+		case SDT_YES_NO:
+			result = code ? SDR_NO : SDR_YES;
+			break;
+		case SDT_OK_CANCEL:
+			result = code ? SDR_CANCEL : SDR_OK;
+			break;
+		default:
+			break;
+	}
+
+	return result;
+}
+
+#else
+
+SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message)
+{
+	switch (type)
+	{
+		case SDT_INFO:
+			std::cout << "INFO: ";
+			break;
+		case SDT_WARNING:
+			std::cout << "WARNING:";
+			break;
+		case SDT_ERROR:
+			std::cout << "ERROR: ";
+			break;
+		case SDT_YES_NO:
+		case SDT_OK_CANCEL:
+			std::cout << "QUESTION: ";
+			break;
+	}
+
+	std::cout << message << std::endl;
+
+	std::string line;
+
+	SystemDialogResult result = SDR_OK;
+
+	bool done = false;
+	while (!done)
+	{
+		switch (type)
+		{
+			case SDT_INFO:
+			case SDT_WARNING:
+			case SDT_ERROR:
+				std::cout << "Press ENTER to continue";
+				break;
+
+			case SDT_YES_NO:
+				std::cout << "Type 'Y' for Yes or 'N' for No";
+				break;
+
+			case SDT_OK_CANCEL:
+				std::cout << "Type 'O' for OK or 'C' for Cancel";
+				break;
+		}
+
+		std::getline(std::cin, line);
+
+		switch (type)
+		{
+			case SDT_INFO:
+			case SDT_WARNING:
+			case SDT_ERROR:
+				done = true;
+				break;
+
+			case SDT_YES_NO:
+				if (line == "Y" || line == "y")
+				{
+					result = SDR_YES;
+					done = true;
+				}
+				else if (line == "N" || line == "n")
+				{
+					result = SDR_NO;
+					done = true;
+				}
+				break;
+
+			case SDT_OK_CANCEL:
+				if (line == "O" || line == "o")
+				{
+					done = true;
+					result = SDR_OK;
+				}
+				else if (line == "C" || line == "c")
+				{
+					done = true;
+					result = SDR_CANCEL;
+				}
+				break;
+		}
+	}
+
+	return result;
+}
+#endif // if defined(PLATFORM_WINDOWS)
diff --git a/src/app/system.h b/src/app/system.h
new file mode 100644
index 00000000..fd1c0516
--- /dev/null
+++ b/src/app/system.h
@@ -0,0 +1,57 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see  http://www.gnu.org/licenses/.
+
+// system.h
+
+#pragma once
+
+
+#include <string>
+
+
+/**
+ * \enum SysDialogType Type of system dialog
+ */
+enum SystemDialogType
+{
+	//! Information message
+	SDT_INFO,
+	//! Warning message
+	SDT_WARNING,
+	//! Error message
+	SDT_ERROR,
+	//! Yes/No question
+	SDT_YES_NO,
+	//! Ok/Cancel question
+	SDT_OK_CANCEL
+};
+
+/**
+ * \enum SysDialogResult Result of system dialog
+ *
+ * Means which button was pressed.
+ */
+enum SystemDialogResult
+{
+	SDR_OK,
+	SDR_CANCEL,
+	SDR_YES,
+	SDR_NO
+};
+
+//! Displays a system dialog
+SystemDialogResult SystemDialog(SystemDialogType, const std::string &title, const std::string &message);
diff --git a/src/common/config.h.cmake b/src/common/config.h.cmake
new file mode 100644
index 00000000..b0663872
--- /dev/null
+++ b/src/common/config.h.cmake
@@ -0,0 +1,8 @@
+#pragma once
+
+// Macros set by CMake
+#cmakedefine DEBUG
+#cmakedefine PLATFORM_WINDOWS @PLATFORM_WINDOWS@
+#cmakedefine PLATFORM_LINUX @PLATFORM_LINUX@
+#cmakedefine PLATFORM_OTHER @PLATFORM_OTHER@
+
diff --git a/src/common/event.cpp b/src/common/event.cpp
index b323e430..0a56fb94 100644
--- a/src/common/event.cpp
+++ b/src/common/event.cpp
@@ -16,16 +16,23 @@
 
 // event.cpp
 
-
-#include <windows.h>
-#include <stdio.h>
-
-#include "common/struct.h"
 #include "common/iman.h"
 #include "common/event.h"
 
+#include <string.h>
 
 
+Event::Event()
+{
+	event = EVENT_NULL;
+	param = 0;
+	axeX = 0.0f;
+	axeY = 0.0f;
+	axeZ = 0.0f;
+	keyState = 0;
+	rTime = 0.0f;
+}
+
 
 // Object's constructor.
 
@@ -57,7 +64,7 @@ void CEvent::Flush()
 
 void CEvent::MakeEvent(Event &event, EventMsg msg)
 {
-	ZeroMemory(&event, sizeof(Event));
+	memset(&event, 0, sizeof(Event));
 	event.event = msg;
 }
 
diff --git a/src/common/event.h b/src/common/event.h
index 0dc6cedc..95e303cd 100644
--- a/src/common/event.h
+++ b/src/common/event.h
@@ -538,6 +538,8 @@ struct Event
 	float		axeZ;		// control the Z axis (-1 .. 1)
 	short		keyState;	// state of the keyboard (KS_ *)
 	float		rTime;		// relative time
+
+	Event();
 };
 
 
@@ -619,8 +621,6 @@ public:
 	bool	AddEvent(const Event &event);
 	bool	GetEvent(Event &event);
 
-protected:
-
 protected:
 	CInstanceManager* m_iMan;
 
diff --git a/src/common/iman.cpp b/src/common/iman.cpp
index 139f56a5..53735a48 100644
--- a/src/common/iman.cpp
+++ b/src/common/iman.cpp
@@ -17,7 +17,6 @@
 // iman.cpp
 
 
-#include <windows.h>
 #include <stdio.h>
 
 #include "common/struct.h"
diff --git a/src/common/restext.h b/src/common/restext.h
index 019f67a8..241951a6 100644
--- a/src/common/restext.h
+++ b/src/common/restext.h
@@ -19,12 +19,12 @@
 #pragma once
 
 
-
-
-#include "old/d3dengine.h"
 #include "common/event.h"
 
 
+class CD3DEngine;
+
+
 
 
 // Possible types of the text resources.
diff --git a/src/common/struct.h b/src/common/struct.h
index eb0078b7..b143334d 100644
--- a/src/common/struct.h
+++ b/src/common/struct.h
@@ -19,8 +19,6 @@
 #pragma once
 
 
-#include <d3d.h>
-
 #include <math/vector.h>
 
 
diff --git a/src/graphics/common/camera.h b/src/graphics/common/camera.h
index 59e76097..28397b93 100644
--- a/src/graphics/common/camera.h
+++ b/src/graphics/common/camera.h
@@ -20,7 +20,6 @@
 #pragma once
 
 #include "engine.h"
-#include "common/struct.h"
 #include "common/event.h"
 
 
diff --git a/src/graphics/common/cloud.h b/src/graphics/common/cloud.h
index 579eb9a5..9ca8c113 100644
--- a/src/graphics/common/cloud.h
+++ b/src/graphics/common/cloud.h
@@ -19,10 +19,10 @@
 
 #pragma once
 
-#include "common/struct.h"
 #include "common/event.h"
 #include "graphics/common/color.h"
 #include "math/point.h"
+#include "math/vector.h"
 
 
 
diff --git a/src/graphics/common/device.cpp b/src/graphics/common/device.cpp
new file mode 100644
index 00000000..2e3db61b
--- /dev/null
+++ b/src/graphics/common/device.cpp
@@ -0,0 +1,14 @@
+#include "graphics/common/device.h"
+
+//! Sets the default values
+Gfx::DeviceConfig::DeviceConfig()
+{
+	width = 800;
+	height = 600;
+	bpp = 16;
+	fullScreen = false;
+	resizeable = false;
+	hardwareAccel = true;
+	doubleBuf = true;
+	noFrame = false;
+}
\ No newline at end of file
diff --git a/src/graphics/common/device.h b/src/graphics/common/device.h
index a8bf32cd..cd52fa5a 100644
--- a/src/graphics/common/device.h
+++ b/src/graphics/common/device.h
@@ -22,6 +22,28 @@
 
 namespace Gfx {
 
+struct DeviceConfig
+{
+	//! Screen width
+	int width;
+	//! Screen height
+	int height;
+	//! Bits per pixel
+	int bpp;
+	//! Full screen
+	bool fullScreen;
+	//! Resizeable window
+	bool resizeable;
+	//! Hardware acceleration
+	bool hardwareAccel;
+	//! Double buffering
+	bool doubleBuf;
+	//! No window frame (also set with full screen)
+	bool noFrame;
+
+	DeviceConfig();
+};
+
 class CDevice
 {
   // TODO
diff --git a/src/graphics/common/engine.cpp b/src/graphics/common/engine.cpp
index acd09953..29857ce3 100644
--- a/src/graphics/common/engine.cpp
+++ b/src/graphics/common/engine.cpp
@@ -19,5 +19,55 @@
 
 #include "graphics/common/engine.h"
 
+#include <GL/gl.h>
+#include <GL/glu.h>
+
 
 // TODO implementation
+
+Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
+{
+	// TODO
+}
+
+Gfx::CEngine::~CEngine()
+{
+	// TODO
+}
+
+int Gfx::CEngine::Render()
+{
+	/* Just a hello world for now */
+
+	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+	glShadeModel(GL_SMOOTH);
+	glDisable(GL_DEPTH_TEST);
+	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	gluOrtho2D(-10.0f, 10.0f, -10.0f, 10.0f);
+
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	//glTranslatef(0.0f, 0.0f, -6.0f);
+
+	glBegin(GL_TRIANGLES);
+	{
+		glColor3f(1.0f, 0.0f, 0.0f);
+		glVertex2f(-2.0f, -1.0f);
+		glColor3f(0.0f, 1.0f, 0.0f);
+		glVertex2f(2.0f, -1.0f);
+		glColor3f(0.0f, 0.0f, 1.0f);
+		glVertex2f(0.0f, 1.5f);
+	}
+	glEnd();
+
+	glFlush();
+
+	return 1;
+}
diff --git a/src/graphics/common/lightning.h b/src/graphics/common/lightning.h
index 2077954c..8edf9e52 100644
--- a/src/graphics/common/lightning.h
+++ b/src/graphics/common/lightning.h
@@ -20,11 +20,11 @@
 #pragma once
 
 #include "common/misc.h"
-#include "common/struct.h"
-#include "object/object.h"
+#include "math/vector.h"
 
 
 class CInstanceManager;
+class CObject;
 class CSound;
 
 
diff --git a/src/graphics/common/model.h b/src/graphics/common/model.h
index d67c71a1..349c15cd 100644
--- a/src/graphics/common/model.h
+++ b/src/graphics/common/model.h
@@ -20,7 +20,6 @@
 #pragma once
 
 #include "engine.h"
-#include "common/struct.h"
 #include "common/event.h"
 #include "modfile.h"
 #include "vertex.h"
diff --git a/src/graphics/common/particle.h b/src/graphics/common/particle.h
index 9e9fd365..4047cb5e 100644
--- a/src/graphics/common/particle.h
+++ b/src/graphics/common/particle.h
@@ -305,7 +305,7 @@ protected:
 	void		DrawParticuleWheel(int i);
 	CObject*	SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father);
 	CObject*	SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father);
-	void		Play(Sound sound, Math::Vector pos, float amplitude);
+	void		Play(Snd::Sound sound, Math::Vector pos, float amplitude);
 	bool		TrackMove(int i, Math::Vector pos, float progress);
 	void		TrackDraw(int i, ParticuleType type);
 
diff --git a/src/graphics/common/planet.h b/src/graphics/common/planet.h
index 2bf4d990..4ffccfc4 100644
--- a/src/graphics/common/planet.h
+++ b/src/graphics/common/planet.h
@@ -19,7 +19,6 @@
 
 #pragma once
 
-#include "common/struct.h"
 #include "common/event.h"
 #include "math/point.h"
 
diff --git a/src/graphics/common/pyro.h b/src/graphics/common/pyro.h
index 704febff..e6b58443 100644
--- a/src/graphics/common/pyro.h
+++ b/src/graphics/common/pyro.h
@@ -19,9 +19,11 @@
 
 #pragma once
 
-#include "graphics/common/engine.h"
-#include "object/object.h"
 #include "common/misc.h"
+#include "graphics/common/engine.h"
+//#include "object/object.h"
+// TEMPORARILY!
+enum ObjectType {};
 
 
 class CInstanceManager;
@@ -93,7 +95,7 @@ public:
 	CPyro(CInstanceManager* iMan);
 	~CPyro();
 
-	void		DeleteObject(bool bAll=FALSE);
+	void		DeleteObject(bool bAll=false);
 	bool		Create(PyroType type, CObject* pObj, float force=1.0f);
 	bool		EventProcess(const Event &event);
 	Error		IsEnded();
diff --git a/src/object/brain.cpp b/src/object/brain.cpp
index 1ffe1b51..afc99033 100644
--- a/src/object/brain.cpp
+++ b/src/object/brain.cpp
@@ -62,7 +62,7 @@
 #include "ui/window.h"
 #include "ui/displaytext.h"
 #include "old/text.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "old/particule.h"
 #include "script/cmdtoken.h"
 
diff --git a/src/object/object.cpp b/src/object/object.cpp
index 10cc190a..6931bd2b 100644
--- a/src/object/object.cpp
+++ b/src/object/object.cpp
@@ -85,7 +85,7 @@
 #include "ui/displaytext.h"
 #include "script/cmdtoken.h"
 #include "script/cbottoken.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "object/object.h"
 
 
diff --git a/src/object/object.h b/src/object/object.h
index 9d77ae16..735da8a5 100644
--- a/src/object/object.h
+++ b/src/object/object.h
@@ -21,7 +21,7 @@
 
 #include "old/d3dengine.h"
 #include "old/camera.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 
 
 class CInstanceManager;
diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp
index a897349a..902c1cba 100644
--- a/src/object/robotmain.cpp
+++ b/src/object/robotmain.cpp
@@ -69,7 +69,7 @@
 #include "ui/edit.h"
 #include "ui/displaytext.h"
 #include "old/text.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "script/cbottoken.h"
 #include "script/cmdtoken.h"
 #include "object/mainmovie.h"
diff --git a/src/old/blitz.cpp b/src/old/blitz.cpp
index b73bd3ef..15488d22 100644
--- a/src/old/blitz.cpp
+++ b/src/old/blitz.cpp
@@ -35,7 +35,7 @@
 #include "old/camera.h"
 #include "object/auto/auto.h"
 #include "object/auto/autopara.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "old/blitz.h"
 
 
diff --git a/src/old/d3dapp.cpp b/src/old/d3dapp.cpp
index 0614fc35..7f042798 100644
--- a/src/old/d3dapp.cpp
+++ b/src/old/d3dapp.cpp
@@ -35,7 +35,7 @@
 #include "old/math3d.h"
 #include "old/joystick.h"
 #include "object/robotmain.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "old/d3dapp.h"
 
 // fix for "MSH_MOUSEWHEEL undefined" error
diff --git a/src/old/d3dengine.cpp b/src/old/d3dengine.cpp
index 305adc2f..e28483de 100644
--- a/src/old/d3dengine.cpp
+++ b/src/old/d3dengine.cpp
@@ -44,7 +44,7 @@
 #include "old/cloud.h"
 #include "old/blitz.h"
 #include "old/planet.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 
 
 
diff --git a/src/old/particule.cpp b/src/old/particule.cpp
index 3fb77919..8c8a1620 100644
--- a/src/old/particule.cpp
+++ b/src/old/particule.cpp
@@ -38,7 +38,7 @@
 #include "object/auto/auto.h"
 #include "object/robotmain.h"
 #include "old/terrain.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "old/water.h"
 #include "old/particule.h"
 
diff --git a/src/old/particule.h b/src/old/particule.h
index 004decee..23d0899e 100644
--- a/src/old/particule.h
+++ b/src/old/particule.h
@@ -21,7 +21,7 @@
 
 #include "math/point.h"
 #include "old/d3dengine.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 
 
 class CInstanceManager;
diff --git a/src/old/pyro.cpp b/src/old/pyro.cpp
index 72f370e3..fc61e62b 100644
--- a/src/old/pyro.cpp
+++ b/src/old/pyro.cpp
@@ -39,7 +39,7 @@
 #include "object/motion/motion.h"
 #include "object/motion/motionhuman.h"
 #include "ui/displaytext.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "old/pyro.h"
 
 
diff --git a/src/old/sound.cpp b/src/old/sound.cpp
new file mode 100644
index 00000000..8b4089a6
--- /dev/null
+++ b/src/old/sound.cpp
@@ -0,0 +1,1659 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see  http://www.gnu.org/licenses/.
+
+// sound.cpp
+
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <d3dtypes.h>
+#include <dsound.h>
+#include <stdio.h>
+
+#include "common/language.h"
+#include "common/struct.h"
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/math3d.h"
+#include "old/sound.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+const int LXIMAGE = 640;
+const int LYIMAGE = 480;
+
+
+
+// Header .WAV file.
+
+struct WaveHeader
+{
+	BYTE		RIFF[4];		// "RIFF"
+	DWORD		dwSize; 		// size of data to follow
+	BYTE		WAVE[4];		// "WAVE"
+	BYTE		fmt_[4];		// "fmt "
+	DWORD		dw16;			// 16
+	WORD		wOne_0; 		// 1
+	WORD		wChnls; 		// number of Channels
+	DWORD		dwSRate;		// sample Rate
+	DWORD		BytesPerSec;		// sample Rate
+	WORD		wBlkAlign;		// 1
+	WORD		BitsPerSample;		// sample size
+	BYTE		DATA[4];		// "DATA"
+	DWORD		dwDSize;		// number of Samples
+};
+
+
+
+
+// Displays an error DirectSound.
+
+void DisplayError(char *name, Sound sound, HRESULT err)
+{
+	char	s[100];
+	unsigned int i = err;
+	if ( err == DS_OK )  return;
+	sprintf(s, "SoundError in %s, sound=%d err=%d\n", name, sound, i);
+	OutputDebugString(s);
+
+	if ( err == DSERR_ALLOCATED )  OutputDebugString("DSERR_ALLOCATED\n");
+	if ( err == DSERR_CONTROLUNAVAIL )  OutputDebugString("DSERR_CONTROLUNAVAIL\n");
+	if ( err == DSERR_INVALIDPARAM )  OutputDebugString("DSERR_INVALIDPARAM\n");
+	if ( err == DSERR_INVALIDCALL )  OutputDebugString("DSERR_INVALIDCALL\n");
+	if ( err == DSERR_GENERIC )  OutputDebugString("DSERR_GENERIC\n");
+	if ( err == DSERR_PRIOLEVELNEEDED )  OutputDebugString("DSERR_PRIOLEVELNEEDED\n");
+	if ( err == DSERR_OUTOFMEMORY )  OutputDebugString("DSERR_OUTOFMEMORY\n");
+	if ( err == DSERR_BADFORMAT )  OutputDebugString("DSERR_BADFORMAT\n");
+	if ( err == DSERR_UNSUPPORTED )  OutputDebugString("DSERR_UNSUPPORTED\n");
+	if ( err == DSERR_NODRIVER )  OutputDebugString("DSERR_NODRIVER\n");
+	if ( err == DSERR_ALREADYINITIALIZED )  OutputDebugString("DSERR_ALREADYINITIALIZED\n");
+	if ( err == DSERR_NOAGGREGATION )  OutputDebugString("DSERR_NOAGGREGATION\n");
+	if ( err == DSERR_BUFFERLOST )  OutputDebugString("DSERR_BUFFERLOST\n");
+	if ( err == DSERR_OTHERAPPHASPRIO )  OutputDebugString("DSERR_OTHERAPPHASPRIO\n");
+	if ( err == DSERR_UNINITIALIZED )  OutputDebugString("DSERR_UNINITIALIZED\n");
+	if ( err == DSERR_NOINTERFACE )  OutputDebugString("DSERR_NOINTERFACE\n");
+	if ( err == DSERR_ACCESSDENIED )  OutputDebugString("DSERR_ACCESSDENIED\n");
+}
+
+// Returns the name of the current folder.
+
+void GetCurrentDir(char *pName, int lg)
+{
+	int		i;
+
+	strncpy(pName, _pgmptr, lg-1);
+	pName[lg-1] = 0;
+
+	lg = strlen(pName);
+	if ( lg == 0 )  return;
+
+	for ( i=0 ; i<lg ; i++ )
+	{
+		pName[i] = tolower(pName[i]);
+	}
+
+	while ( lg > 0 )
+	{
+		lg --;
+		if ( pName[lg] == '\\' )
+		{
+			pName[lg+1] = 0;
+			break;
+		}
+	}
+
+	if ( lg > 6 && strcmp(pName+lg-6, "\\debug\\") == 0 )
+	{
+		pName[lg-5] = 0;  // ignores the folder \debug!
+	}
+
+	if ( lg > 6 && strcmp(pName+lg-6, "\\release\\") == 0 )
+	{
+		pName[lg-7] = 0;  // ignores the folder \release !
+	}
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Changes the volume of midi.
+// The volume is between 0 and 20!
+
+void InitMidiVolume(int volume)
+{
+	int			nb, i, n;
+	MMRESULT		result;
+	HMIDIOUT		hmo = 0;
+
+	static int table[21] =
+	{
+		0x00000000,
+		0x11111111,
+		0x22222222,
+		0x33333333,
+		0x44444444,
+		0x55555555,
+		0x66666666,
+		0x77777777,
+		0x88888888,
+		0x99999999,
+		0xAAAAAAAA,
+		0xBBBBBBBB,
+		0xCCCCCCCC,
+		0xDDDDDDDD,
+		0xEEEEEEEE,
+		0xF222F222,
+		0xF555F555,
+		0xF777F777,
+		0xFAAAFAAA,
+		0xFDDDFDDD,
+		0xFFFFFFFF,
+	};
+
+	if ( volume < 0         )  volume = 0;
+	if ( volume > MAXVOLUME )  volume = MAXVOLUME;
+
+	nb = midiOutGetNumDevs();
+	for ( i=0 ; i<nb ; i++ )
+	{
+		result = midiOutOpen((LPHMIDIOUT)&hmo, i, 0L, 0L, 0L);
+		if ( result != MMSYSERR_NOERROR )
+		{
+			continue;
+		}
+
+		result = midiOutSetVolume(hmo, table[volume]);
+		if ( result != MMSYSERR_NOERROR )
+		{
+			n = 1;
+		}
+		midiOutClose(hmo);
+		hmo = 0;
+	}
+}
+
+// Changes the volume of audio CD.
+// The volume is between 0 and 20!
+// Crashing in Vista. The current craft (if _SOUNDTRACKS = true) no longer crashes,
+// but this is not the correct volume which is modified!
+
+bool InitAudioTrackVolume(int volume)
+{
+#if _SOUNDTRACKS
+	MMRESULT rc;			  // Return code.
+	HMIXER hMixer;			  // Mixer handle used in mixer API calls.
+	MIXERCONTROL mxc;		  // Holds the mixer control data.
+	MIXERLINE mxl;			  // Holds the mixer line data.
+	MIXERLINECONTROLS mxlc;   // Obtains the mixer control.
+
+	if ( volume < 0         )  volume = 0;
+	if ( volume > MAXVOLUME )  volume = MAXVOLUME;
+
+	// Open the mixer. This opens the mixer with a deviceID of 0. If you
+	// have a single sound card/mixer, then this will open it. If you have
+	// multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and
+	// so on.
+	rc = mixerOpen(&hMixer, 0,0,0,0);
+	if ( rc != MMSYSERR_NOERROR )
+	{
+		return false;  // Couldn't open the mixer.
+	}
+
+	// Initialize MIXERLINE structure.
+	ZeroMemory(&mxl,sizeof(mxl));
+	mxl.cbStruct = sizeof(mxl);
+
+	// Specify the line you want to get. You are getting the input line
+	// here. If you want to get the output line, you need to use
+	// MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
+	mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
+
+	rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
+						   MIXER_GETLINEINFOF_COMPONENTTYPE);
+	if ( rc != MMSYSERR_NOERROR )
+	{
+		return false;  // Couldn't get the mixer line.
+	}
+
+	// Get the control.
+	ZeroMemory(&mxlc, sizeof(mxlc));
+	mxlc.cbStruct = sizeof(mxlc);
+	mxlc.dwLineID = mxl.dwLineID;
+//?	mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
+//?	mxlc.dwControlType = MIXERCONTROL_CONTROLF_UNIFORM;
+	mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
+	mxlc.cControls = 1;
+	mxlc.cbmxctrl = sizeof(mxc);
+	mxlc.pamxctrl = &mxc;
+	ZeroMemory(&mxc, sizeof(mxc));
+	mxc.cbStruct = sizeof(mxc);
+	rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
+							   MIXER_GETLINECONTROLSF_ONEBYTYPE);
+//?							   MIXER_GETLINECONTROLSF_ALL);
+	if ( rc != MMSYSERR_NOERROR )
+	{
+		return false;  // Couldn't get the control.
+	}
+
+	// After successfully getting the peakmeter control, the volume range
+	// will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum.
+
+	MIXERCONTROLDETAILS mxcd;			  // Gets the control values.
+	MIXERCONTROLDETAILS_SIGNED volStruct; // Gets the control values.
+
+	volStruct.lValue = volume*(mxc.Bounds.lMaximum-mxc.Bounds.lMinimum);
+	volStruct.lValue /= MAXVOLUME;
+	volStruct.lValue += mxc.Bounds.lMinimum;
+
+	// Initialize the MIXERCONTROLDETAILS structure
+	ZeroMemory(&mxcd, sizeof(mxcd));
+	mxcd.cbStruct = sizeof(mxcd);
+	mxcd.cbDetails = sizeof(volStruct);
+	mxcd.dwControlID = mxc.dwControlID;
+	mxcd.paDetails = &volStruct;
+	mxcd.cChannels = 1;
+
+	// Get the current value of the peakmeter control. Typically, you
+	// would set a timer in your program to query the volume every 10th
+	// of a second or so.
+	rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
+								 MIXER_SETCONTROLDETAILSF_VALUE);
+	if ( rc != MMSYSERR_NOERROR )
+	{
+		return false;  // Couldn't get the current volume.
+	}
+#endif
+
+	return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Constructor.
+
+CSound::CSound(CInstanceManager* iMan)
+{
+	int		i;
+	
+	m_iMan = iMan;
+	m_iMan->AddInstance(CLASS_SOUND, this);
+
+	m_bEnable        = false;
+	m_bState         = false;
+	m_bAudioTrack    = true;
+	m_ctrl3D         = true;
+	m_bDebugMode     = false;
+	m_MidiDeviceID   = 0;
+	m_MIDIMusic      = 0;
+	m_audioVolume    = 20;
+	m_midiVolume     = 15;
+	m_lastMidiVolume = 0;
+	m_listener       = 0;
+	m_lastTime       = 0.0f;
+	m_playTime       = 0.0f;
+	m_uniqueStamp    = 0;
+	m_maxSound       = MAXSOUND;
+	m_eye            = Math::Vector(0.0f, 0.0f, 0.0f);
+	m_hWnd           = 0;
+
+	m_lpDS = NULL;
+
+	ZeroMemory(m_channel, sizeof(SoundChannel)*MAXSOUND);
+	for ( i=0 ; i<MAXSOUND ; i++ )
+	{
+		m_channel[i].bUsed = false;
+	}
+
+	for ( i=0 ; i<MAXFILES ; i++ )
+	{
+		m_files[i] = 0;
+	}
+}
+
+// Destructor.
+
+CSound::~CSound()
+{
+	int		i;
+
+	if ( m_bEnable )
+	{
+		InitMidiVolume(15);  // gives an average volume!
+		InitAudioTrackVolume(15);  // gives an average volume!
+	}
+
+	for ( i=0 ; i<MAXSOUND ; i++ )
+	{
+		if ( m_channel[i].bUsed )
+		{
+			m_channel[i].soundBuffer->Stop();
+			m_channel[i].soundBuffer->Release();
+			m_channel[i].soundBuffer = 0;
+			m_channel[i].bUsed = false;
+		}
+	}
+
+	if ( m_listener != NULL )
+	{
+		m_listener->Release();
+		m_listener = NULL;
+	}
+
+	if ( m_lpDS != NULL )
+	{
+		m_lpDS->Release();
+		m_lpDS = NULL;
+	}
+}
+
+
+// Specifies whether you are in debug mode.
+
+void CSound::SetDebugMode(bool bMode)
+{
+	m_bDebugMode = bMode;
+}
+
+
+// Initializes DirectSound.
+
+bool CSound::Create(HWND hWnd, bool b3D)
+{
+	LPDIRECTSOUNDBUFFER primary;
+	DSBUFFERDESC		dsbdesc;
+	DSCAPS				dscaps;
+	WAVEFORMATEX		wfx;
+	HRESULT 			hr;
+
+	if ( !DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK )
+	{
+		OutputDebugString("Fatal error: DirectSoundCreate\n");
+		m_bEnable = false;
+		return false;
+	}
+
+//?	m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
+	m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
+
+	if ( !RetSound3DCap() )  b3D = false;
+
+	m_ctrl3D = false;
+	if ( b3D )
+	{
+		// Obtain primary buffer, asking it for 3D control.
+		ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
+		dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+		dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
+		hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
+		if ( hr == S_OK )
+		{
+			m_ctrl3D = true;
+		}
+	}
+
+	if ( !m_ctrl3D )
+	{
+		// Obtain primary buffer, without 3D control.
+		ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
+		dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+		dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
+		hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
+		if ( hr != S_OK )
+		{
+			return false;
+		}
+		m_ctrl3D = false;
+	}
+
+	if ( m_ctrl3D )
+	{
+		hr = primary->QueryInterface( IID_IDirectSound3DListener, 
+									  (VOID**)&m_listener );
+		if ( hr != S_OK )
+		{
+			primary->Release();
+			return false;
+		}
+	}
+
+	// Set primary buffer format to 44kHz and 16-bit output.
+	ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
+	wfx.wFormatTag		= WAVE_FORMAT_PCM;
+	wfx.nChannels		= 2;
+	wfx.nSamplesPerSec	= 22050;
+//?	wfx.nSamplesPerSec	= 44100;
+	wfx.wBitsPerSample	= 16;
+	wfx.nBlockAlign 	= wfx.wBitsPerSample / 8 * wfx.nChannels;
+	wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+	hr = primary->SetFormat(&wfx);
+	if ( hr != S_OK )
+	{
+		DisplayError("SetFormat", SOUND_CLICK, hr);
+	}
+
+	// Release the primary buffer, since it is not need anymore.
+	primary->Release();
+
+	// Search the maximum possible voices.
+	if ( m_ctrl3D )
+	{
+		ZeroMemory( &dscaps, sizeof(DSCAPS) );
+		dscaps.dwSize = sizeof(DSCAPS);
+		hr = m_lpDS->GetCaps(&dscaps);
+		if ( hr == DS_OK )
+		{
+			m_maxSound = dscaps.dwMaxHwMixingAllBuffers;
+			if ( dscaps.dwMaxHw3DAllBuffers > 0 &&
+				 m_maxSound > (int)dscaps.dwMaxHw3DAllBuffers )
+			{
+				m_maxSound = dscaps.dwMaxHw3DAllBuffers;
+			}
+			if ( m_maxSound > MAXSOUND )  m_maxSound = MAXSOUND;
+		}
+	}
+
+	m_bEnable = true;
+	m_hWnd    = hWnd;
+	return true;
+}
+
+
+// Indicates whether to play sounds in 3D or not.
+
+void CSound::SetSound3D(bool bMode)
+{
+	StopAll();
+
+	if ( m_listener != NULL )
+	{
+		m_listener->Release();
+		m_listener = NULL;
+	}
+
+	if ( m_lpDS != NULL )
+	{
+		m_lpDS->Release();
+		m_lpDS = NULL;
+	}
+
+	Create(m_hWnd, bMode);
+}
+
+bool CSound::RetSound3D()
+{
+	return m_ctrl3D;
+}
+
+// Indicates whether it is possible to play sounds in 3D.
+
+bool CSound::RetSound3DCap()
+{
+	DSCAPS		dscaps;
+	HRESULT 	hr;
+
+	ZeroMemory( &dscaps, sizeof(DSCAPS) );
+	dscaps.dwSize = sizeof(DSCAPS);
+	hr = m_lpDS->GetCaps(&dscaps);
+	if ( hr != DS_OK )  return false;
+
+	return ( dscaps.dwMaxHw3DAllBuffers > 0 );
+}
+
+
+
+// Returns the state of DirectSound.
+
+bool CSound::RetEnable()
+{
+	return m_bEnable;
+}
+
+
+// Switches on or off the sound.
+
+void CSound::SetState(bool bState)
+{
+	m_bState = bState;
+}
+
+// Specifies the pathname to the CD.
+
+void CSound::SetCDpath(char *path)
+{
+	strcpy(m_CDpath, path);
+}
+
+// Switches on or off the CD-audio music.
+
+void CSound::SetAudioTrack(bool bAudio)
+{
+	m_bAudioTrack = bAudio;
+}
+
+
+// Manages volumes of audio (. Wav) and midi (. Mid).
+
+void CSound::SetAudioVolume(int volume)
+{
+	m_audioVolume = volume;
+}
+
+int CSound::RetAudioVolume()
+{
+	if ( !m_bEnable )  return 0;
+	return m_audioVolume;
+}
+
+void CSound::SetMidiVolume(int volume)
+{
+	m_midiVolume = volume;
+
+	if ( m_bAudioTrack )
+	{
+		InitAudioTrackVolume(m_midiVolume);
+	}
+}
+
+int CSound::RetMidiVolume()
+{
+	if ( !m_bEnable )  return 0;
+	return m_midiVolume;
+}
+
+
+// Reads a file.
+
+bool CSound::ReadFile(Sound sound, char *metaname, char *filename)
+{
+	WaveHeader	wavHdr;
+	DWORD		size;
+	int			err;
+
+	// Open the wave file.
+	err = g_metafile.Open(metaname, filename);
+	if ( err != 0 ) return false;
+
+	// Read in the wave header.
+	g_metafile.Read(&wavHdr, sizeof(wavHdr));
+
+	// Figure out the size of the data region.
+	size = wavHdr.dwDSize;
+
+	if ( m_files[sound] != 0 )
+	{
+		free(m_files[sound]);
+	}
+	m_files[sound] = (char*)malloc(sizeof(WaveHeader)+size);
+
+	memcpy(m_files[sound], &wavHdr, sizeof(WaveHeader));
+	g_metafile.Read(m_files[sound]+sizeof(WaveHeader), size);
+
+	// Close out the wave file.
+	g_metafile.Close();
+	return true;
+}
+
+// Hides all sound files (. Wav).
+
+void CSound::CacheAll()
+{
+	int			i;
+	char		meta[50];
+	char		name[50];
+
+	if ( !m_bEnable )  return;
+
+	if ( m_bDebugMode )
+	{
+		strcpy(meta, "");
+	}
+	else
+	{
+#if _SCHOOL
+		strcpy(meta, "ceebot3.dat");
+#else
+		strcpy(meta, "colobot3.dat");
+#endif
+	}
+
+	for ( i=0 ; i<MAXFILES ; i++ )
+	{
+		if ( m_bDebugMode )
+		{
+			sprintf(name, "sound\\sound%.3d.wav", i);
+		}
+		else
+		{
+			sprintf(name, "sound%.3d.wav", i);
+		}
+		if ( !ReadFile((Sound)i, meta, name) )  break;
+	}
+}
+
+
+// Return the priority of a sound.
+// The higher the value, the greater the sound is important.
+
+int CSound::RetPriority(Sound sound)
+{
+	if ( sound == SOUND_FLYh   ||
+		 sound == SOUND_FLY    ||
+		 sound == SOUND_MOTORw ||
+		 sound == SOUND_MOTORt ||
+		 sound == SOUND_MOTORr ||
+		 sound == SOUND_MOTORs ||
+		 sound == SOUND_SLIDE  ||
+		 sound == SOUND_ERROR  )
+	{
+		return 30;
+	}
+
+	if ( sound == SOUND_CONVERT  ||
+		 sound == SOUND_ENERGY   ||
+		 sound == SOUND_DERRICK  ||
+		 sound == SOUND_STATION  ||
+		 sound == SOUND_REPAIR   ||
+		 sound == SOUND_RESEARCH ||
+		 sound == SOUND_BURN     ||
+		 sound == SOUND_BUILD    ||
+		 sound == SOUND_TREMBLE  ||
+		 sound == SOUND_NUCLEAR  ||
+		 sound == SOUND_EXPLO    ||
+		 sound == SOUND_EXPLOl   ||
+		 sound == SOUND_EXPLOlp  ||
+		 sound == SOUND_EXPLOp   ||
+		 sound == SOUND_EXPLOi   )
+	{
+		return 20;
+	}
+
+	if ( sound == SOUND_BLUP    ||
+		 sound == SOUND_INSECTs ||
+		 sound == SOUND_INSECTa ||
+		 sound == SOUND_INSECTb ||
+		 sound == SOUND_INSECTw ||
+		 sound == SOUND_INSECTm ||
+		 sound == SOUND_PSHHH   ||
+		 sound == SOUND_EGG     )
+	{
+		return 0;
+	}
+
+	return 10;
+}
+
+// Seeks a free buffer.
+
+bool CSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
+{
+	DWORD	status;
+	int		i, priority;
+
+	priority = RetPriority(sound);
+
+#if 1
+	// Seeks a channel used which sound is stopped.
+	for ( i=0 ; i<m_maxSound ; i++ )
+	{
+		if ( !m_channel[i].bUsed )  continue;
+		if ( m_channel[i].type != sound )  continue;
+
+		m_channel[i].soundBuffer->GetStatus(&status);
+		if ( (status&DSBSTATUS_PLAYING) == 0 )
+		{
+			m_channel[i].priority = priority;
+			m_channel[i].uniqueStamp = m_uniqueStamp++;
+			channel = i;
+			bAlreadyLoaded = true;
+			return true;
+		}
+	}
+#endif
+
+	// Seeks a channel completely free.
+	for ( i=0 ; i<m_maxSound ; i++ )
+	{
+		if ( !m_channel[i].bUsed )
+		{
+			m_channel[i].priority = priority;
+			m_channel[i].uniqueStamp = m_uniqueStamp++;
+			channel = i;
+			bAlreadyLoaded = false;
+			return true;
+		}
+	}
+
+	// Seeks a channel used which sound is stopped.
+	for ( i=0 ; i<m_maxSound ; i++ )
+	{
+		if ( !m_channel[i].bUsed )  continue;
+
+		m_channel[i].soundBuffer->GetStatus(&status);
+		if ( (status&DSBSTATUS_PLAYING) == 0 )
+		{
+			m_channel[i].soundBuffer->Release();
+			m_channel[i].soundBuffer = 0;
+			m_channel[i].priority = priority;
+			m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+			channel = i;
+			bAlreadyLoaded = false;
+			return true;
+		}
+	}
+
+	// Seeks a lower priority channel used.
+	for ( i=0 ; i<m_maxSound ; i++ )
+	{
+		if ( !m_channel[i].bUsed )  continue;
+		if ( m_channel[i].priority >= priority )  continue;
+
+		m_channel[i].soundBuffer->Stop();
+		m_channel[i].soundBuffer->Release();
+		m_channel[i].soundBuffer = 0;
+		m_channel[i].priority = priority;
+		m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+		channel = i;
+		bAlreadyLoaded = false;
+		return true;
+	}
+
+	// Seeks a channel used the same or lower priority.
+	for ( i=0 ; i<m_maxSound ; i++ )
+	{
+		if ( !m_channel[i].bUsed )  continue;
+		if ( m_channel[i].priority > priority )  continue;
+
+		m_channel[i].soundBuffer->Stop();
+		m_channel[i].soundBuffer->Release();
+		m_channel[i].soundBuffer = 0;
+		m_channel[i].priority = priority;
+		m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+		channel = i;
+		bAlreadyLoaded = false;
+		return true;
+	}
+
+	char s[100];
+	sprintf(s, "Sound %d forget (priority=%d)\n", sound, priority);
+	OutputDebugString(s);
+
+	return false;
+}
+
+// Reads in data from a wave file.
+
+bool CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size) 
+{
+	LPVOID	pData1;
+	DWORD	dwData1Size;
+	LPVOID	pData2;
+	DWORD	dwData2Size;
+	HRESULT hr;
+
+	// Lock data in buffer for writing.
+	hr = lpDSB->Lock(0, size, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
+	if ( hr != DS_OK )
+	{
+		return false;
+	}
+
+	// Read in first chunk of data.
+	if ( dwData1Size > 0 ) 
+	{
+		memcpy(pData1, m_files[sound]+sizeof(WaveHeader), dwData1Size);
+	}
+
+	// Read in second chunk if necessary.
+	if ( dwData2Size > 0 ) 
+	{
+		memcpy(pData2, m_files[sound]+sizeof(WaveHeader)+dwData1Size, dwData2Size);
+	}
+
+	// Unlock data in buffer.
+	hr = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
+	if ( hr != DS_OK )
+	{
+		return false;
+	}
+
+	return true;
+}
+
+// Creates a DirectSound buffer.
+
+bool CSound::CreateSoundBuffer(int channel, DWORD size, DWORD freq,
+							   DWORD bitsPerSample, DWORD blkAlign,
+							   bool bStereo)
+{
+	PCMWAVEFORMAT	pcmwf;
+	DSBUFFERDESC	dsbdesc;
+	DS3DBUFFER		bufferParams;  // 3D buffer properties
+	HRESULT 		hr;
+	
+	// Set up wave format structure.
+	memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
+	pcmwf.wf.wFormatTag 	 = WAVE_FORMAT_PCM; 	 
+	pcmwf.wf.nChannels		 = bStereo ? 2 : 1;
+	pcmwf.wf.nSamplesPerSec  = freq;
+	pcmwf.wf.nBlockAlign	 = (WORD)blkAlign;
+	pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
+	pcmwf.wBitsPerSample	 = (WORD)bitsPerSample;
+
+	// Set up DSBUFFERDESC structure.
+	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));	// Zero it out. 
+	dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+	if ( m_ctrl3D )
+	{
+		dsbdesc.dwFlags = DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE|
+						  DSBCAPS_LOCDEFER|
+						  DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY;
+	}
+	else
+	{
+		dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY;
+	}
+	dsbdesc.dwBufferBytes = size; 
+	dsbdesc.lpwfxFormat   = (LPWAVEFORMATEX)&pcmwf;
+
+	hr = m_lpDS->CreateSoundBuffer(&dsbdesc, &m_channel[channel].soundBuffer, NULL);
+	if ( hr != DS_OK )  return false;
+
+	if ( m_ctrl3D )
+	{
+		hr = m_channel[channel].soundBuffer->QueryInterface
+							(
+								IID_IDirectSound3DBuffer, 
+								(VOID**)&m_channel[channel].soundBuffer3D
+							);
+		if ( hr != DS_OK )  return false;
+	}
+	
+	m_channel[channel].bUsed = true;
+	m_channel[channel].bMute = false;
+	return true;
+}
+
+// Creates a DirectSound buffer from a wave file.
+
+bool CSound::CreateBuffer(int channel, Sound sound)
+{
+	WaveHeader* wavHdr;
+	DWORD		size;
+	bool		bStereo;
+
+	if ( m_files[sound] == 0 )  return false;
+
+	wavHdr = (WaveHeader*)m_files[sound];
+	size = wavHdr->dwDSize;
+	bStereo = wavHdr->wChnls > 1 ? true : false;
+
+	// Create the sound buffer for the wave file.
+	if ( !CreateSoundBuffer(channel, size, wavHdr->dwSRate,
+							wavHdr->BitsPerSample, wavHdr->wBlkAlign, bStereo) )
+	{
+		return false;
+	}
+
+	// Read the data for the wave file into the sound buffer.
+	if ( !ReadData(m_channel[channel].soundBuffer, sound, size) )
+	{
+		return false;
+	}
+
+	m_channel[channel].type = sound;
+
+	// Close out the wave file.
+	return true;
+}
+
+// Calculates the volume and pan of a sound, non-3D mode.
+
+void CSound::ComputeVolumePan2D(int channel, const Math::Vector &pos)
+{
+	float	dist, a, g;
+
+	if ( pos.x == m_eye.x &&
+		 pos.y == m_eye.y &&
+		 pos.z == m_eye.z )
+	{
+		m_channel[channel].volume = 1.0f;  // maximum volume
+		m_channel[channel].pan    = 0.0f;  // at the center
+		return;
+	}
+
+#if _TEEN
+	dist = Math::Distance(pos, m_eye);
+	if ( dist >= 210.0f )  // very far?
+	{
+		m_channel[channel].volume = 0.0f;  // silence
+		m_channel[channel].pan    = 0.0f;  // at the center
+		return;
+	}
+	if ( dist <= 10.0f )  // very close?
+	{
+		m_channel[channel].volume = 1.0f;  // maximum volume
+		m_channel[channel].pan    = 0.0f;  // at the center
+		return;
+	}
+	m_channel[channel].volume = 1.0f-((dist-10.0f)/200.0f);
+#else
+	dist = Math::Distance(pos, m_eye);
+	if ( dist >= 110.0f )  // very far?
+	{
+		m_channel[channel].volume = 0.0f;  // silence
+		m_channel[channel].pan    = 0.0f;  // at the center
+		return;
+	}
+	if ( dist <= 10.0f )  // very close?
+	{
+		m_channel[channel].volume = 1.0f;  // maximum volume
+		m_channel[channel].pan    = 0.0f;  // at the center
+		return;
+	}
+	m_channel[channel].volume = 1.0f-((dist-10.0f)/100.0f);
+#endif
+
+	a = Math::RotateAngle(m_lookat.x-m_eye.x, m_eye.z-m_lookat.z);
+	g = Math::RotateAngle(pos.x-m_eye.x, m_eye.z-pos.z);
+	m_channel[channel].pan = sinf(Math::Direction(a, g));
+}
+
+// Sounds in the middle.
+// Returns the associated channel or -1.
+
+int CSound::Play(Sound sound, float amplitude, float frequency, bool bLoop)
+{
+	return Play(sound, m_lookat, amplitude, frequency, bLoop);
+}
+
+// Sounds at a given position.
+// Returns the associated channel or -1.
+
+int CSound::Play(Sound sound, Math::Vector pos,
+				 float amplitude, float frequency, bool bLoop)
+{
+	DS3DBUFFER	sb;
+	int			channel, iVolume, iPan, iFreq, uniqueStamp;
+	bool		bAlreadyLoaded;
+	DWORD		flag, freq;
+	HRESULT		err;
+
+	if ( !m_bEnable )  return -1;
+	if ( !m_bState || m_audioVolume == 0 )  return -1;
+
+//?	if ( Math::Distance(pos, m_eye) > 100.0f )  return -1;
+
+	if ( !SearchFreeBuffer(sound, channel, bAlreadyLoaded) )  return -1;
+
+	if ( !bAlreadyLoaded )
+	{
+		if ( !CreateBuffer(channel, sound) )
+		{
+			if ( m_channel[channel].bUsed            &&
+				 m_channel[channel].soundBuffer != 0 )
+			{
+				m_channel[channel].soundBuffer->Release();
+				m_channel[channel].soundBuffer = 0;
+			}
+			m_channel[channel].bUsed = false;
+			return -1;
+		}
+	}
+
+	m_channel[channel].pos = pos;
+
+	if ( m_ctrl3D )
+	{
+		m_channel[channel].volume = 1.0f;
+		m_channel[channel].pan    = 0.0f;
+	}
+	else
+	{
+		ComputeVolumePan2D(channel, pos);
+	}
+
+#if 0
+	DWORD status;
+	m_channel[channel].soundBuffer->GetStatus(&status);
+	char s[100];
+	sprintf(s, "Play sound=%d status=%d channel=%d flag=%d\n", sound, status, channel, bAlreadyLoaded);
+	OutputDebugString(s);
+#endif
+
+	m_channel[channel].oper[0].bUsed = false;
+	m_channel[channel].startAmplitude = amplitude;
+	m_channel[channel].startFrequency = frequency;
+	m_channel[channel].changeFrequency = 1.0f;
+
+	if ( m_ctrl3D )
+	{
+		sb.dwSize = sizeof(DS3DBUFFER);
+		err = m_channel[channel].soundBuffer3D->GetAllParameters(&sb);
+		DisplayError("GetAllParameters", sound, err);
+
+		sb.vPosition = VEC_TO_D3DVEC(pos);
+//?		sb.dwInsideConeAngle = 90;
+//?		sb.dwOutsideConeAngle = 180;
+//?		sb.vConeOrientation = Math::Vector(0.0f, 1.0f, 0.0f);
+		sb.lConeOutsideVolume = DSBVOLUME_MIN;
+#if _TEEN
+		sb.flMinDistance = 50.0f;
+#else
+		sb.flMinDistance = 20.0f;
+#endif
+		sb.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
+
+		err = m_channel[channel].soundBuffer3D->SetAllParameters(&sb, DS3D_IMMEDIATE);
+		DisplayError("SetAllParameters", sound, err);
+	}
+
+	amplitude *= m_channel[channel].volume;
+	amplitude *= (float)m_audioVolume/MAXVOLUME;
+	iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+	if ( iVolume > 0 )  iVolume = 0;
+	err = m_channel[channel].soundBuffer->SetVolume(iVolume);
+	DisplayError("SetVolume", sound, err);
+
+	if ( !m_ctrl3D )
+	{
+		iPan = (int)(m_channel[channel].pan*10000.0f);
+		err = m_channel[channel].soundBuffer->SetPan(iPan);
+		DisplayError("SetPan", sound, err);
+	}
+
+	if ( !bAlreadyLoaded )
+	{
+		err = m_channel[channel].soundBuffer->GetFrequency(&freq);
+		DisplayError("GetFrequency", sound, err);
+		m_channel[channel].initFrequency = freq;
+	}
+	iFreq = (int)(frequency*m_channel[channel].initFrequency);
+	err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+	DisplayError("SetFrequency", sound, err);
+
+	err = m_channel[channel].soundBuffer->SetCurrentPosition(0);
+	DisplayError("SetCurrentPosition", sound, err);
+
+	flag = bLoop?DSBPLAY_LOOPING:0;
+//?	flag |= DSBPLAY_LOCHARDWARE|DSBPLAY_TERMINATEBY_DISTANCE;
+//?	flag |= DSBPLAY_TERMINATEBY_DISTANCE;
+	err = m_channel[channel].soundBuffer->Play(0, 0, flag);
+	DisplayError("Play", sound, err);
+	if ( err == DSERR_BADFORMAT )
+	{
+		iFreq = m_channel[channel].initFrequency;
+		err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+		DisplayError("SetFrequency (repeat)", sound, err);
+
+		err = m_channel[channel].soundBuffer->Play(0, 0, flag);
+		DisplayError("Play (repeat)", sound, err);
+	}
+
+	uniqueStamp = m_channel[channel].uniqueStamp;
+	return channel | ((uniqueStamp&0xffff)<<16);
+}
+
+// Check a channel number.
+// Adapts the channel, so it can be used as an offset in m_channel.
+
+bool CSound::CheckChannel(int &channel)
+{
+	int		uniqueStamp;
+
+	uniqueStamp = (channel>>16)&0xffff;
+	channel &= 0xffff;
+
+	if ( !m_bEnable )  return false;
+	if ( !m_bState || m_audioVolume == 0 )  return false;
+
+	if ( channel < 0 || channel >= m_maxSound )  return false;
+	if ( !m_channel[channel].bUsed )  return false;
+
+	if ( m_channel[channel].uniqueStamp != uniqueStamp )  return false;
+
+	return true;
+}
+
+// Removes all envelopes.
+
+bool CSound::FlushEnvelope(int channel)
+{
+	if ( !CheckChannel(channel) )  return false;
+
+	m_channel[channel].oper[0].bUsed = false;
+	return true;
+}
+
+// Adds an operation envelope.
+
+bool CSound::AddEnvelope(int channel, float amplitude, float frequency,
+						 float time, SoundNext oper)
+{
+	int		i;
+
+	if ( !CheckChannel(channel) )  return false;
+
+	for ( i=0 ; i<MAXOPER ; i++ )
+	{
+		if ( m_channel[channel].oper[i].bUsed )  continue;
+
+		m_channel[channel].oper[i].bUsed = true;
+		m_channel[channel].oper[i].finalAmplitude = amplitude;
+		m_channel[channel].oper[i].finalFrequency = frequency;
+		m_channel[channel].oper[i].totalTime = time;
+		m_channel[channel].oper[i].currentTime = 0;
+		m_channel[channel].oper[i].nextOper = oper;
+
+		if ( i < MAXOPER-1 )
+		{
+			m_channel[channel].oper[i+1].bUsed = false;
+		}
+		return true;
+	}
+	return false;
+}
+
+// Changes the position of a sound.
+
+bool CSound::Position(int channel, Math::Vector pos)
+{
+	float		amplitude, pan;
+	int			iVolume, iPan;
+	HRESULT		err;
+
+	if ( !CheckChannel(channel) )  return false;
+
+	m_channel[channel].pos = pos;
+
+	if ( m_ctrl3D )
+	{
+		m_channel[channel].soundBuffer3D->SetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED);
+	}
+	else
+	{
+		ComputeVolumePan2D(channel, pos);
+
+		if ( !m_channel[channel].oper[0].bUsed )
+		{
+			amplitude = m_channel[channel].startAmplitude;
+			amplitude *= m_channel[channel].volume;
+			amplitude *= (float)m_audioVolume/MAXVOLUME;
+			iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+			if ( iVolume > 0 )  iVolume = 0;
+			err = m_channel[channel].soundBuffer->SetVolume(iVolume);
+			DisplayError("SetVolume", m_channel[channel].type, err);
+		}
+
+		pan = m_channel[channel].pan;
+		iPan = (int)(pan*10000.0f);
+		err = m_channel[channel].soundBuffer->SetPan(iPan);
+		DisplayError("SetPan", m_channel[channel].type, err);
+	}
+	return true;
+}
+
+// Changes the frequency of a sound.
+// 0.5 down of an octave and 2.0 up of an octave.
+
+bool CSound::Frequency(int channel, float frequency)
+{
+	HRESULT	err;
+	int		iFreq;
+
+	if ( !CheckChannel(channel) )  return false;
+
+	m_channel[channel].changeFrequency = frequency;
+
+	if ( !m_channel[channel].oper[0].bUsed )
+	{
+		iFreq = (int)(frequency*m_channel[channel].initFrequency);
+		err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+		DisplayError("Frequency", m_channel[channel].type, err);
+	}
+
+	return true;
+}
+
+// Stops sound.
+
+bool CSound::Stop(int channel)
+{
+	if ( !CheckChannel(channel) )  return false;
+
+	m_channel[channel].soundBuffer->Stop();
+	return true;
+}
+
+// Stops all sounds.
+
+bool CSound::StopAll()
+{
+	DWORD	status;
+	int 	i;
+
+	for ( i=0 ; i<MAXSOUND ; i++ )
+	{
+		if ( !m_channel[i].bUsed )  continue;
+
+		m_channel[i].soundBuffer->GetStatus(&status);
+		if ( (status&DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING )
+		{
+			m_channel[i].soundBuffer->Stop();
+		}
+		m_channel[i].soundBuffer->Stop();
+		m_channel[i].soundBuffer->Release();
+		m_channel[i].soundBuffer = 0;
+
+		m_channel[i].bUsed = false;
+	}
+	return true;
+}
+
+// Silent all sounds.
+
+bool CSound::MuteAll(bool bMute)
+{
+	int 	i;
+
+	for ( i=0 ; i<MAXSOUND ; i++ )
+	{
+		if ( !m_channel[i].bUsed )  continue;
+
+		m_channel[i].bMute = bMute;
+	}
+	return true;
+}
+
+
+// Passes the following operation for a channel.
+
+void CSound::OperNext(int channel)
+{
+	int		i;
+
+	m_channel[channel].startAmplitude = m_channel[channel].oper[0].finalAmplitude;
+	m_channel[channel].startFrequency = m_channel[channel].oper[0].finalFrequency;
+
+	for ( i=0 ; i<MAXOPER-1 ; i++ )
+	{
+		if ( !m_channel[channel].oper[i+1].bUsed )  break;
+
+		m_channel[channel].oper[i] = m_channel[channel].oper[i+1];
+	}
+
+	m_channel[channel].oper[i].bUsed = false;
+}
+
+// Updates the sound buffers.
+
+void CSound::FrameMove(float rTime)
+{
+	HRESULT		err;
+	SoundNext	next;
+	float		progress, volume, freq;
+	int			i, iVolume, iFreq;
+
+	m_playTime += rTime;
+
+	for ( i=0 ; i<m_maxSound ; i++ )
+	{
+		if ( !m_channel[i].bUsed )  continue;
+		if ( !m_channel[i].oper[0].bUsed )  continue;
+
+		if ( m_channel[i].bMute )
+		{
+			m_channel[i].soundBuffer->SetVolume(-10000);  // silence
+			continue;
+		}
+
+		m_channel[i].oper[0].currentTime += rTime;
+
+		progress = m_channel[i].oper[0].currentTime / m_channel[i].oper[0].totalTime;
+		if ( progress > 1.0f )  progress = 1.0f;
+
+		volume = progress;
+		volume *= m_channel[i].oper[0].finalAmplitude-m_channel[i].startAmplitude;
+		volume += m_channel[i].startAmplitude;
+		volume *= m_channel[i].volume;
+		volume *= (float)m_audioVolume/MAXVOLUME;
+		iVolume = (int)((powf(volume, 0.2f)-1.0f)*10000.0f);
+		if ( iVolume > 0 )  iVolume = 0;
+		m_channel[i].soundBuffer->SetVolume(iVolume);
+
+		freq = progress;
+		freq *= m_channel[i].oper[0].finalFrequency-m_channel[i].startFrequency;
+		freq += m_channel[i].startFrequency;
+		freq *= m_channel[i].changeFrequency;
+		iFreq = (int)(freq*m_channel[i].initFrequency);
+		err = m_channel[i].soundBuffer->SetFrequency(iFreq);
+		DisplayError("FrameMove::Frequency", m_channel[i].type, err);
+
+		if ( m_channel[i].oper[0].currentTime >=
+			 m_channel[i].oper[0].totalTime )
+		{
+			next = m_channel[i].oper[0].nextOper;
+
+			if ( next == SOPER_LOOP )
+			{
+				m_channel[i].oper[0].currentTime = 0.0f;
+			}
+			else
+			{
+				OperNext(i);
+
+				if ( next == SOPER_STOP )
+				{
+					m_channel[i].soundBuffer->Stop();
+				}
+			}
+		}
+	}
+
+	m_lastTime += rTime;
+	if ( m_lastTime >= 0.05f && m_listener != 0 )
+	{
+		m_lastTime = 0.0f;
+		m_listener->CommitDeferredSettings();
+	}
+}
+
+// Specifies the position of the listener.
+// Must be called whenever the camera moves.
+
+void CSound::SetListener(Math::Vector eye, Math::Vector lookat)
+{
+	DS3DLISTENER	listenerParams;
+	HRESULT			err;
+	float			amplitude, pan;
+	int				i, iVolume, iPan;
+
+	m_eye = eye;
+	m_lookat = lookat;
+
+	if ( m_listener == 0 )
+	{
+		if ( m_ctrl3D )  return;
+
+		for ( i=0 ; i<m_maxSound ; i++ )
+		{
+			if ( !m_channel[i].bUsed )  continue;
+
+			ComputeVolumePan2D(i, m_channel[i].pos);
+
+			if ( !m_channel[i].oper[0].bUsed )
+			{
+				amplitude = m_channel[i].startAmplitude;
+				amplitude *= m_channel[i].volume;
+				amplitude *= (float)m_audioVolume/MAXVOLUME;
+				iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+				if ( iVolume > 0 )  iVolume = 0;
+				err = m_channel[i].soundBuffer->SetVolume(iVolume);
+				DisplayError("SetVolume", m_channel[i].type, err);
+			}
+
+			pan = m_channel[i].pan;
+			iPan = (int)(pan*10000.0f);
+			err = m_channel[i].soundBuffer->SetPan(iPan);
+			DisplayError("SetPan", m_channel[i].type, err);
+		}
+		return;
+	}
+
+	// Get listener parameters.
+	listenerParams.dwSize = sizeof(DS3DLISTENER);
+	m_listener->GetAllParameters(&listenerParams);
+
+	listenerParams.vPosition = VEC_TO_D3DVEC(eye);
+	listenerParams.vOrientFront = VEC_TO_D3DVEC(lookat-eye);
+	listenerParams.vOrientTop = D3DVECTOR(0.0f, 1.0f, 0.0f);
+	listenerParams.flDistanceFactor = 10.0f;
+	listenerParams.flRolloffFactor = 1.0f;
+
+	m_listener->SetAllParameters(&listenerParams, DS3D_DEFERRED);
+}
+
+
+
+
+// Uses MCI to play a MIDI file. The window procedure
+// is notified when playback is complete.
+
+bool CSound::PlayMusic(int rank, bool bRepeat)
+{
+	MCI_OPEN_PARMS	mciOpenParms;
+	MCI_PLAY_PARMS	mciPlayParms;
+	DWORD			dwReturn;
+	char			filename[MAX_PATH];
+
+	m_bRepeatMusic = bRepeat;
+	m_playTime = 0.0f;
+
+	if ( m_midiVolume == 0 )  return true;
+
+	if ( m_bAudioTrack )
+	{
+		return PlayAudioTrack(rank);
+	}
+
+	if ( !m_bEnable )  return true;
+	InitMidiVolume(m_midiVolume);
+	m_lastMidiVolume = m_midiVolume;
+
+	GetCurrentDir(filename, MAX_PATH-30);
+	sprintf(filename+strlen(filename), "sound\\music%.3d.blp", rank-1);
+
+	// Open the device by specifying the device and filename.
+	// MCI will attempt to choose the MIDI mapper as the output port.
+	mciOpenParms.lpstrDeviceType = "sequencer";
+	mciOpenParms.lpstrElementName = filename;
+	dwReturn = mciSendCommand(NULL,
+							  MCI_OPEN,
+							  MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,
+							  (DWORD)(LPVOID)&mciOpenParms);
+	if ( dwReturn != 0 )
+	{
+		mciGetErrorString(dwReturn, filename, 128);
+		// Failed to open device. Don't close it; just return error.
+		return false;
+	}
+
+	// The device opened successfully; get the device ID.
+	m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+	// Begin playback. 
+	mciPlayParms.dwCallback = (DWORD)m_hWnd;
+	dwReturn = mciSendCommand(m_MidiDeviceID,
+							  MCI_PLAY,
+							  MCI_NOTIFY, 
+							  (DWORD)(LPVOID)&mciPlayParms);
+	if ( dwReturn != 0 )
+	{
+		mciGetErrorString(dwReturn, filename, 128);
+		StopMusic();
+		return false;
+	}
+
+	m_MIDIMusic = rank;
+	return true;
+}
+
+// Uses MCI to play a CD-audio track. The window procedure
+// is notified when playback is complete.
+// The rank parameter is in space [1..n] !
+// For CD mix (data/audio), it will be [2..n] !
+
+bool CSound::PlayAudioTrack(int rank)
+{
+#if _SOUNDTRACKS
+	MCI_OPEN_PARMS	mciOpenParms;
+	MCI_PLAY_PARMS	mciPlayParms;
+	MCI_SET_PARMS	mciSetParms;
+	DWORD			dwReturn;
+	char			filename[MAX_PATH];
+	char			device[10];
+
+	if ( !m_bEnable )  return true;
+//?	if ( m_midiVolume == 0 )  return true;
+	InitAudioTrackVolume(m_midiVolume);
+	m_lastMidiVolume = m_midiVolume;
+
+	// Open the device by specifying the device and filename.
+	// MCI will attempt to choose the MIDI mapper as the output port.
+	memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
+//?	mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
+//?	dwReturn = mciSendCommand(NULL,
+//?							  MCI_OPEN,
+//?							  MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
+//?							  (DWORD)(LPVOID)&mciOpenParms);
+	mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
+	if ( m_CDpath[0] == 0 )
+	{
+		dwReturn = mciSendCommand(NULL,
+								  MCI_OPEN,
+								  MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
+								  (DWORD)(LPVOID)&mciOpenParms);
+	}
+	else
+	{
+		device[0] = m_CDpath[0];
+		device[1] = ':';
+		device[2] = 0;
+		mciOpenParms.lpstrElementName = device;
+		dwReturn = mciSendCommand(NULL,
+								  MCI_OPEN,
+								  MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
+								  (DWORD)(LPVOID)&mciOpenParms);
+	}
+	if ( dwReturn != 0 )
+	{
+		mciGetErrorString(dwReturn, filename, 128);
+		// Failed to open device. Don't close it; just return error.
+		return false;
+	}
+
+	// The device opened successfully; get the device ID.
+	m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+	// Set the time format to track/minute/second/frame (TMSF).
+	memset(&mciSetParms, 0, sizeof(MCI_SET_PARMS));
+	mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
+	dwReturn = mciSendCommand(m_MidiDeviceID,
+							  MCI_SET,
+							  MCI_SET_TIME_FORMAT,
+							  (DWORD)&mciSetParms);
+	if ( dwReturn != 0 )
+	{
+		mciGetErrorString(dwReturn, filename, 128);
+		StopMusic();
+		return false;
+	}  
+
+	// Begin playback.
+	memset(&mciPlayParms, 0, sizeof(MCI_PLAY_PARMS));
+	mciPlayParms.dwCallback = (DWORD)m_hWnd;
+	mciPlayParms.dwFrom = MCI_MAKE_TMSF(rank+0, 0, 0, 0);
+	mciPlayParms.dwTo   = MCI_MAKE_TMSF(rank+1, 0, 0, 0);
+	dwReturn = mciSendCommand(m_MidiDeviceID,
+							  MCI_PLAY,
+							  MCI_NOTIFY|MCI_FROM|MCI_TO,
+							  (DWORD)(LPVOID)&mciPlayParms);
+	if ( dwReturn != 0 )
+	{
+		mciGetErrorString(dwReturn, filename, 128);
+		StopMusic();
+		return false;
+	}
+
+	m_MIDIMusic = rank;
+#endif
+	return true;
+}
+
+// Restart the MIDI player.
+
+bool CSound::RestartMusic()
+{
+	if ( !m_bRepeatMusic )  return false;
+
+	OutputDebugString("RestartMusic\n");
+	if ( !m_bEnable )  return true;
+//?	if ( m_midiVolume == 0 )  return true;
+	if ( m_MIDIMusic == 0 )  return false;
+	if ( m_playTime < 5.0f )  return false;
+
+	return PlayMusic(m_MIDIMusic, true);
+}
+
+// Shuts down the MIDI player.
+
+void CSound::SuspendMusic()
+{
+	if ( !m_bEnable )  return;
+
+//?	if ( m_MidiDeviceID && m_midiVolume != 0 )
+	if ( m_MidiDeviceID )
+	{
+		if ( m_bAudioTrack )  mciSendCommand(m_MidiDeviceID, MCI_STOP, 0, NULL);
+		mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL);
+	}
+	m_MidiDeviceID = 0;
+}
+
+// Shuts down the MIDI player.
+
+void CSound::StopMusic()
+{
+	SuspendMusic();
+	m_MIDIMusic = 0;
+}
+
+// Returns true if the music is in progress.
+
+bool CSound::IsPlayingMusic()
+{
+	return (m_MIDIMusic != 0);
+}
+
+// Adjusts the volume of currently music, if necessary.
+
+void CSound::AdaptVolumeMusic()
+{
+	if ( m_midiVolume != m_lastMidiVolume )
+	{
+		if ( m_bAudioTrack )
+		{
+			InitAudioTrackVolume(m_midiVolume);
+		}
+		else
+		{
+			InitMidiVolume(m_midiVolume);
+		}
+		m_lastMidiVolume = m_midiVolume;
+		RestartMusic();
+	}
+}
+
diff --git a/src/old/sound.h b/src/old/sound.h
new file mode 100644
index 00000000..2dcdc2cf
--- /dev/null
+++ b/src/old/sound.h
@@ -0,0 +1,242 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see  http://www.gnu.org/licenses/.
+
+// sound.h
+
+#pragma once
+
+
+#include <dsound.h>
+
+
+const int MAXFILES	= 200;
+const int MAXSOUND	= 32;
+const int MAXVOLUME	= 20;
+const int MAXOPER	= 4;
+
+class CInstanceManager;
+
+
+enum Sound
+{
+	SOUND_CLICK		= 0,
+	SOUND_BOUM		= 1,
+	SOUND_EXPLO		= 2,
+	SOUND_FLYh		= 3,	// human
+	SOUND_FLY		= 4,
+	SOUND_STEPs		= 5,	// smooth
+	SOUND_MOTORw		= 6,	// wheel
+	SOUND_MOTORt		= 7,	// tank
+	SOUND_MOTORr		= 8,	// roller
+	SOUND_ERROR		= 9,
+	SOUND_CONVERT		= 10,
+	SOUND_ENERGY		= 11,
+	SOUND_PLOUF		= 12,
+	SOUND_BLUP		= 13,
+	SOUND_WARNING		= 14,
+	SOUND_DERRICK		= 15,
+	SOUND_LABO		= 16,
+	SOUND_STATION		= 17,
+	SOUND_REPAIR		= 18,
+	SOUND_RESEARCH		= 19,
+	SOUND_INSECTs		= 20,	// spider
+	SOUND_BURN		= 21,
+	SOUND_TZOING		= 22,
+	SOUND_GGG		= 23,
+	SOUND_MANIP		= 24,
+	SOUND_FIRE		= 25,	// shooting with fireball
+	SOUND_HUMAN1		= 26,	// breathing
+	SOUND_STEPw		= 27,	// water
+	SOUND_SWIM		= 28,
+	SOUND_RADAR		= 29,
+	SOUND_BUILD		= 30,
+	SOUND_ALARM		= 31,	// energy alarm
+	SOUND_SLIDE		= 32,
+	SOUND_EXPLOi		= 33,	// insect
+	SOUND_INSECTa		= 34,	// ant
+	SOUND_INSECTb		= 35,	// bee
+	SOUND_INSECTw		= 36,	// worm
+	SOUND_INSECTm		= 37,	// mother
+	SOUND_TREMBLE		= 38,
+	SOUND_PSHHH		= 39,
+	SOUND_NUCLEAR		= 40,
+	SOUND_INFO		= 41,
+	SOUND_OPEN		= 42,
+	SOUND_CLOSE		= 43,
+	SOUND_FACTORY		= 44,
+	SOUND_EGG		= 45,
+	SOUND_MOTORs		= 46,	// submarine
+	SOUND_MOTORi		= 47,	// insect (legs)
+	SOUND_SHIELD		= 48,
+	SOUND_FIREi		= 49,	// shooting with orgaball (insect)
+	SOUND_GUNDEL		= 50,
+	SOUND_PSHHH2		= 51,	// shield
+	SOUND_MESSAGE		= 52,
+	SOUND_BOUMm		= 53,	// metal
+	SOUND_BOUMv		= 54,	// plant
+	SOUND_BOUMs		= 55,	// smooth
+	SOUND_EXPLOl		= 56,	// little
+	SOUND_EXPLOlp		= 57,	// little power
+	SOUND_EXPLOp		= 58,	// power
+	SOUND_STEPh		= 59,	// hard
+	SOUND_STEPm		= 60,	// metal
+	SOUND_POWERON		= 61,
+	SOUND_POWEROFF		= 62,
+	SOUND_AIE		= 63,
+	SOUND_WAYPOINT		= 64,
+	SOUND_RECOVER		= 65,
+	SOUND_DEADi		= 66,
+	SOUND_JOSTLE		= 67,
+	SOUND_GFLAT		= 68,
+	SOUND_DEADg		= 69,	// shooting death
+	SOUND_DEADw		= 70,	// drowning
+	SOUND_FLYf		= 71,	// reactor fail
+	SOUND_ALARMt		= 72,	// temperature alarm
+	SOUND_FINDING		= 73,	// finds a cache object
+	SOUND_THUMP		= 74,
+	SOUND_TOUCH		= 75,
+	SOUND_BLITZ		= 76,
+	SOUND_MUSHROOM		= 77,
+	SOUND_FIREp		= 78,	// shooting with phazer
+	SOUND_EXPLOg1		= 79,	// impact gun 1
+	SOUND_EXPLOg2		= 80,	// impact gun 2
+	SOUND_MOTORd		= 81,	// engine friction
+};
+
+enum SoundNext
+{
+	SOPER_CONTINUE	= 1,
+	SOPER_STOP		= 2,
+	SOPER_LOOP		= 3,
+};
+
+struct SoundOper
+{
+	char		bUsed;
+	float		finalAmplitude;
+	float		finalFrequency;
+	float		totalTime;
+	float		currentTime;
+	SoundNext	nextOper;
+};
+
+struct SoundChannel
+{
+	char					bUsed;			// buffer used?
+	char					bMute;			// silence?
+	Sound					type;			// SOUND_*
+	int					priority;		// so great -> important
+	Math::Vector				pos;			// position in space
+	unsigned short				uniqueStamp;		// unique marker
+	LPDIRECTSOUNDBUFFER			soundBuffer;
+	LPDIRECTSOUND3DBUFFER			soundBuffer3D;
+	float					startAmplitude;
+	float					startFrequency;
+	float					changeFrequency;
+	int					initFrequency;
+	float					volume;			// 2D: volume 1..0 depending on position
+	float					pan;			// 2D: pan -1..+1 depending on position
+	SoundOper				oper[MAXOPER];
+};
+
+
+
+class CSound
+{
+public:
+	CSound(CInstanceManager* iMan);
+	~CSound();
+
+	void	SetDebugMode(bool bMode);
+	bool	Create(HWND hWnd, bool b3D);
+	void	CacheAll();
+
+	void	SetState(bool bState);
+	bool	RetEnable();
+
+	void	SetCDpath(char *path);
+	void	SetAudioTrack(bool bAudio);
+
+	void	SetSound3D(bool bMode);
+	bool	RetSound3D();
+	bool	RetSound3DCap();
+
+	void	SetAudioVolume(int volume);
+	int		RetAudioVolume();
+	void	SetMidiVolume(int volume);
+	int		RetMidiVolume();
+
+	void	SetListener(Math::Vector eye, Math::Vector lookat);
+	void	FrameMove(float rTime);
+
+	int		Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
+	int		Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
+	bool	FlushEnvelope(int channel);
+	bool	AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
+	bool	Position(int channel, Math::Vector pos);
+	bool	Frequency(int channel, float frequency);
+	bool	Stop(int channel);
+	bool	StopAll();
+	bool	MuteAll(bool bMute);
+
+	bool	PlayMusic(int rank, bool bRepeat);
+	bool	RestartMusic();
+	void	SuspendMusic();
+	void	StopMusic();
+	bool	IsPlayingMusic();
+	void	AdaptVolumeMusic();
+
+protected:
+	bool	CheckChannel(int &channel);
+	bool	CreateSoundBuffer(int channel, DWORD size, DWORD freq, DWORD bitsPerSample, DWORD blkAlign, bool bStereo);
+	bool	ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size);
+	bool	CreateBuffer(int channel, Sound sound);
+	void	ComputeVolumePan2D(int channel, const Math::Vector &pos);
+	bool	ReadFile(Sound sound, char *metaname, char *filename);
+	int		RetPriority(Sound sound);
+	bool	SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
+	void	OperNext(int channel);
+	bool	PlayAudioTrack(int rank);
+
+protected:
+	CInstanceManager*		m_iMan;
+
+	HWND					m_hWnd;
+	bool					m_bEnable;
+	bool					m_bState;
+	bool					m_bAudioTrack;
+	bool					m_ctrl3D;
+	bool					m_bDebugMode;
+	LPDIRECTSOUND			m_lpDS;
+	LPDIRECTSOUND3DLISTENER	m_listener;
+	SoundChannel			m_channel[MAXSOUND];
+	char*					m_files[MAXFILES];
+	UINT					m_MidiDeviceID;
+	int						m_MIDIMusic;
+	bool					m_bRepeatMusic;
+	int						m_audioVolume;
+	int						m_midiVolume;
+	int						m_lastMidiVolume;
+	Math::Vector				m_eye;
+	Math::Vector				m_lookat;
+	float					m_lastTime;
+	float					m_playTime;
+	int						m_uniqueStamp;
+	int						m_maxSound;
+	char					m_CDpath[100];
+};
+
+
diff --git a/src/old/water.cpp b/src/old/water.cpp
index 510d1fef..215bac94 100644
--- a/src/old/water.cpp
+++ b/src/old/water.cpp
@@ -34,7 +34,7 @@
 #include "old/particule.h"
 #include "old/terrain.h"
 #include "object/object.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "old/water.h"
 
 
diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp
index e4420a10..49d7684e 100644
--- a/src/physics/physics.cpp
+++ b/src/physics/physics.cpp
@@ -42,7 +42,7 @@
 #include "object/brain.h"
 #include "object/motion/motion.h"
 #include "object/motion/motionhuman.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "object/task/task.h"
 #include "script/cmdtoken.h"
 #include "physics/physics.h"
diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp
index f3078389..e69de29b 100644
--- a/src/sound/sound.cpp
+++ b/src/sound/sound.cpp
@@ -1,1659 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see  http://www.gnu.org/licenses/.
-
-// sound.cpp
-
-
-#include <stdlib.h>
-#include <ctype.h>
-#include <d3dtypes.h>
-#include <dsound.h>
-#include <stdio.h>
-
-#include "common/language.h"
-#include "common/struct.h"
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/math3d.h"
-#include "sound/sound.h"
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-const int LXIMAGE = 640;
-const int LYIMAGE = 480;
-
-
-
-// Header .WAV file.
-
-struct WaveHeader
-{
-	BYTE		RIFF[4];		// "RIFF"
-	DWORD		dwSize; 		// size of data to follow
-	BYTE		WAVE[4];		// "WAVE"
-	BYTE		fmt_[4];		// "fmt "
-	DWORD		dw16;			// 16
-	WORD		wOne_0; 		// 1
-	WORD		wChnls; 		// number of Channels
-	DWORD		dwSRate;		// sample Rate
-	DWORD		BytesPerSec;		// sample Rate
-	WORD		wBlkAlign;		// 1
-	WORD		BitsPerSample;		// sample size
-	BYTE		DATA[4];		// "DATA"
-	DWORD		dwDSize;		// number of Samples
-};
-
-
-
-
-// Displays an error DirectSound.
-
-void DisplayError(char *name, Sound sound, HRESULT err)
-{
-	char	s[100];
-	unsigned int i = err;
-	if ( err == DS_OK )  return;
-	sprintf(s, "SoundError in %s, sound=%d err=%d\n", name, sound, i);
-	OutputDebugString(s);
-
-	if ( err == DSERR_ALLOCATED )  OutputDebugString("DSERR_ALLOCATED\n");
-	if ( err == DSERR_CONTROLUNAVAIL )  OutputDebugString("DSERR_CONTROLUNAVAIL\n");
-	if ( err == DSERR_INVALIDPARAM )  OutputDebugString("DSERR_INVALIDPARAM\n");
-	if ( err == DSERR_INVALIDCALL )  OutputDebugString("DSERR_INVALIDCALL\n");
-	if ( err == DSERR_GENERIC )  OutputDebugString("DSERR_GENERIC\n");
-	if ( err == DSERR_PRIOLEVELNEEDED )  OutputDebugString("DSERR_PRIOLEVELNEEDED\n");
-	if ( err == DSERR_OUTOFMEMORY )  OutputDebugString("DSERR_OUTOFMEMORY\n");
-	if ( err == DSERR_BADFORMAT )  OutputDebugString("DSERR_BADFORMAT\n");
-	if ( err == DSERR_UNSUPPORTED )  OutputDebugString("DSERR_UNSUPPORTED\n");
-	if ( err == DSERR_NODRIVER )  OutputDebugString("DSERR_NODRIVER\n");
-	if ( err == DSERR_ALREADYINITIALIZED )  OutputDebugString("DSERR_ALREADYINITIALIZED\n");
-	if ( err == DSERR_NOAGGREGATION )  OutputDebugString("DSERR_NOAGGREGATION\n");
-	if ( err == DSERR_BUFFERLOST )  OutputDebugString("DSERR_BUFFERLOST\n");
-	if ( err == DSERR_OTHERAPPHASPRIO )  OutputDebugString("DSERR_OTHERAPPHASPRIO\n");
-	if ( err == DSERR_UNINITIALIZED )  OutputDebugString("DSERR_UNINITIALIZED\n");
-	if ( err == DSERR_NOINTERFACE )  OutputDebugString("DSERR_NOINTERFACE\n");
-	if ( err == DSERR_ACCESSDENIED )  OutputDebugString("DSERR_ACCESSDENIED\n");
-}
-
-// Returns the name of the current folder.
-
-void GetCurrentDir(char *pName, int lg)
-{
-	int		i;
-
-	strncpy(pName, _pgmptr, lg-1);
-	pName[lg-1] = 0;
-
-	lg = strlen(pName);
-	if ( lg == 0 )  return;
-
-	for ( i=0 ; i<lg ; i++ )
-	{
-		pName[i] = tolower(pName[i]);
-	}
-
-	while ( lg > 0 )
-	{
-		lg --;
-		if ( pName[lg] == '\\' )
-		{
-			pName[lg+1] = 0;
-			break;
-		}
-	}
-
-	if ( lg > 6 && strcmp(pName+lg-6, "\\debug\\") == 0 )
-	{
-		pName[lg-5] = 0;  // ignores the folder \debug!
-	}
-
-	if ( lg > 6 && strcmp(pName+lg-6, "\\release\\") == 0 )
-	{
-		pName[lg-7] = 0;  // ignores the folder \release !
-	}
-}
-
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-// Changes the volume of midi.
-// The volume is between 0 and 20!
-
-void InitMidiVolume(int volume)
-{
-	int			nb, i, n;
-	MMRESULT		result;
-	HMIDIOUT		hmo = 0;
-
-	static int table[21] =
-	{
-		0x00000000,
-		0x11111111,
-		0x22222222,
-		0x33333333,
-		0x44444444,
-		0x55555555,
-		0x66666666,
-		0x77777777,
-		0x88888888,
-		0x99999999,
-		0xAAAAAAAA,
-		0xBBBBBBBB,
-		0xCCCCCCCC,
-		0xDDDDDDDD,
-		0xEEEEEEEE,
-		0xF222F222,
-		0xF555F555,
-		0xF777F777,
-		0xFAAAFAAA,
-		0xFDDDFDDD,
-		0xFFFFFFFF,
-	};
-
-	if ( volume < 0         )  volume = 0;
-	if ( volume > MAXVOLUME )  volume = MAXVOLUME;
-
-	nb = midiOutGetNumDevs();
-	for ( i=0 ; i<nb ; i++ )
-	{
-		result = midiOutOpen((LPHMIDIOUT)&hmo, i, 0L, 0L, 0L);
-		if ( result != MMSYSERR_NOERROR )
-		{
-			continue;
-		}
-
-		result = midiOutSetVolume(hmo, table[volume]);
-		if ( result != MMSYSERR_NOERROR )
-		{
-			n = 1;
-		}
-		midiOutClose(hmo);
-		hmo = 0;
-	}
-}
-
-// Changes the volume of audio CD.
-// The volume is between 0 and 20!
-// Crashing in Vista. The current craft (if _SOUNDTRACKS = true) no longer crashes,
-// but this is not the correct volume which is modified!
-
-bool InitAudioTrackVolume(int volume)
-{
-#if _SOUNDTRACKS
-	MMRESULT rc;			  // Return code.
-	HMIXER hMixer;			  // Mixer handle used in mixer API calls.
-	MIXERCONTROL mxc;		  // Holds the mixer control data.
-	MIXERLINE mxl;			  // Holds the mixer line data.
-	MIXERLINECONTROLS mxlc;   // Obtains the mixer control.
-
-	if ( volume < 0         )  volume = 0;
-	if ( volume > MAXVOLUME )  volume = MAXVOLUME;
-
-	// Open the mixer. This opens the mixer with a deviceID of 0. If you
-	// have a single sound card/mixer, then this will open it. If you have
-	// multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and
-	// so on.
-	rc = mixerOpen(&hMixer, 0,0,0,0);
-	if ( rc != MMSYSERR_NOERROR )
-	{
-		return false;  // Couldn't open the mixer.
-	}
-
-	// Initialize MIXERLINE structure.
-	ZeroMemory(&mxl,sizeof(mxl));
-	mxl.cbStruct = sizeof(mxl);
-
-	// Specify the line you want to get. You are getting the input line
-	// here. If you want to get the output line, you need to use
-	// MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
-	mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
-
-	rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
-						   MIXER_GETLINEINFOF_COMPONENTTYPE);
-	if ( rc != MMSYSERR_NOERROR )
-	{
-		return false;  // Couldn't get the mixer line.
-	}
-
-	// Get the control.
-	ZeroMemory(&mxlc, sizeof(mxlc));
-	mxlc.cbStruct = sizeof(mxlc);
-	mxlc.dwLineID = mxl.dwLineID;
-//?	mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
-//?	mxlc.dwControlType = MIXERCONTROL_CONTROLF_UNIFORM;
-	mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
-	mxlc.cControls = 1;
-	mxlc.cbmxctrl = sizeof(mxc);
-	mxlc.pamxctrl = &mxc;
-	ZeroMemory(&mxc, sizeof(mxc));
-	mxc.cbStruct = sizeof(mxc);
-	rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
-							   MIXER_GETLINECONTROLSF_ONEBYTYPE);
-//?							   MIXER_GETLINECONTROLSF_ALL);
-	if ( rc != MMSYSERR_NOERROR )
-	{
-		return false;  // Couldn't get the control.
-	}
-
-	// After successfully getting the peakmeter control, the volume range
-	// will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum.
-
-	MIXERCONTROLDETAILS mxcd;			  // Gets the control values.
-	MIXERCONTROLDETAILS_SIGNED volStruct; // Gets the control values.
-
-	volStruct.lValue = volume*(mxc.Bounds.lMaximum-mxc.Bounds.lMinimum);
-	volStruct.lValue /= MAXVOLUME;
-	volStruct.lValue += mxc.Bounds.lMinimum;
-
-	// Initialize the MIXERCONTROLDETAILS structure
-	ZeroMemory(&mxcd, sizeof(mxcd));
-	mxcd.cbStruct = sizeof(mxcd);
-	mxcd.cbDetails = sizeof(volStruct);
-	mxcd.dwControlID = mxc.dwControlID;
-	mxcd.paDetails = &volStruct;
-	mxcd.cChannels = 1;
-
-	// Get the current value of the peakmeter control. Typically, you
-	// would set a timer in your program to query the volume every 10th
-	// of a second or so.
-	rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
-								 MIXER_SETCONTROLDETAILSF_VALUE);
-	if ( rc != MMSYSERR_NOERROR )
-	{
-		return false;  // Couldn't get the current volume.
-	}
-#endif
-
-	return true;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-// Constructor.
-
-CSound::CSound(CInstanceManager* iMan)
-{
-	int		i;
-	
-	m_iMan = iMan;
-	m_iMan->AddInstance(CLASS_SOUND, this);
-
-	m_bEnable        = false;
-	m_bState         = false;
-	m_bAudioTrack    = true;
-	m_ctrl3D         = true;
-	m_bDebugMode     = false;
-	m_MidiDeviceID   = 0;
-	m_MIDIMusic      = 0;
-	m_audioVolume    = 20;
-	m_midiVolume     = 15;
-	m_lastMidiVolume = 0;
-	m_listener       = 0;
-	m_lastTime       = 0.0f;
-	m_playTime       = 0.0f;
-	m_uniqueStamp    = 0;
-	m_maxSound       = MAXSOUND;
-	m_eye            = Math::Vector(0.0f, 0.0f, 0.0f);
-	m_hWnd           = 0;
-
-	m_lpDS = NULL;
-
-	ZeroMemory(m_channel, sizeof(SoundChannel)*MAXSOUND);
-	for ( i=0 ; i<MAXSOUND ; i++ )
-	{
-		m_channel[i].bUsed = false;
-	}
-
-	for ( i=0 ; i<MAXFILES ; i++ )
-	{
-		m_files[i] = 0;
-	}
-}
-
-// Destructor.
-
-CSound::~CSound()
-{
-	int		i;
-
-	if ( m_bEnable )
-	{
-		InitMidiVolume(15);  // gives an average volume!
-		InitAudioTrackVolume(15);  // gives an average volume!
-	}
-
-	for ( i=0 ; i<MAXSOUND ; i++ )
-	{
-		if ( m_channel[i].bUsed )
-		{
-			m_channel[i].soundBuffer->Stop();
-			m_channel[i].soundBuffer->Release();
-			m_channel[i].soundBuffer = 0;
-			m_channel[i].bUsed = false;
-		}
-	}
-
-	if ( m_listener != NULL )
-	{
-		m_listener->Release();
-		m_listener = NULL;
-	}
-
-	if ( m_lpDS != NULL )
-	{
-		m_lpDS->Release();
-		m_lpDS = NULL;
-	}
-}
-
-
-// Specifies whether you are in debug mode.
-
-void CSound::SetDebugMode(bool bMode)
-{
-	m_bDebugMode = bMode;
-}
-
-
-// Initializes DirectSound.
-
-bool CSound::Create(HWND hWnd, bool b3D)
-{
-	LPDIRECTSOUNDBUFFER primary;
-	DSBUFFERDESC		dsbdesc;
-	DSCAPS				dscaps;
-	WAVEFORMATEX		wfx;
-	HRESULT 			hr;
-
-	if ( !DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK )
-	{
-		OutputDebugString("Fatal error: DirectSoundCreate\n");
-		m_bEnable = false;
-		return false;
-	}
-
-//?	m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
-	m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
-
-	if ( !RetSound3DCap() )  b3D = false;
-
-	m_ctrl3D = false;
-	if ( b3D )
-	{
-		// Obtain primary buffer, asking it for 3D control.
-		ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
-		dsbdesc.dwSize = sizeof(DSBUFFERDESC);
-		dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
-		hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
-		if ( hr == S_OK )
-		{
-			m_ctrl3D = true;
-		}
-	}
-
-	if ( !m_ctrl3D )
-	{
-		// Obtain primary buffer, without 3D control.
-		ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
-		dsbdesc.dwSize = sizeof(DSBUFFERDESC);
-		dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
-		hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
-		if ( hr != S_OK )
-		{
-			return false;
-		}
-		m_ctrl3D = false;
-	}
-
-	if ( m_ctrl3D )
-	{
-		hr = primary->QueryInterface( IID_IDirectSound3DListener, 
-									  (VOID**)&m_listener );
-		if ( hr != S_OK )
-		{
-			primary->Release();
-			return false;
-		}
-	}
-
-	// Set primary buffer format to 44kHz and 16-bit output.
-	ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
-	wfx.wFormatTag		= WAVE_FORMAT_PCM;
-	wfx.nChannels		= 2;
-	wfx.nSamplesPerSec	= 22050;
-//?	wfx.nSamplesPerSec	= 44100;
-	wfx.wBitsPerSample	= 16;
-	wfx.nBlockAlign 	= wfx.wBitsPerSample / 8 * wfx.nChannels;
-	wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
-	hr = primary->SetFormat(&wfx);
-	if ( hr != S_OK )
-	{
-		DisplayError("SetFormat", SOUND_CLICK, hr);
-	}
-
-	// Release the primary buffer, since it is not need anymore.
-	primary->Release();
-
-	// Search the maximum possible voices.
-	if ( m_ctrl3D )
-	{
-		ZeroMemory( &dscaps, sizeof(DSCAPS) );
-		dscaps.dwSize = sizeof(DSCAPS);
-		hr = m_lpDS->GetCaps(&dscaps);
-		if ( hr == DS_OK )
-		{
-			m_maxSound = dscaps.dwMaxHwMixingAllBuffers;
-			if ( dscaps.dwMaxHw3DAllBuffers > 0 &&
-				 m_maxSound > (int)dscaps.dwMaxHw3DAllBuffers )
-			{
-				m_maxSound = dscaps.dwMaxHw3DAllBuffers;
-			}
-			if ( m_maxSound > MAXSOUND )  m_maxSound = MAXSOUND;
-		}
-	}
-
-	m_bEnable = true;
-	m_hWnd    = hWnd;
-	return true;
-}
-
-
-// Indicates whether to play sounds in 3D or not.
-
-void CSound::SetSound3D(bool bMode)
-{
-	StopAll();
-
-	if ( m_listener != NULL )
-	{
-		m_listener->Release();
-		m_listener = NULL;
-	}
-
-	if ( m_lpDS != NULL )
-	{
-		m_lpDS->Release();
-		m_lpDS = NULL;
-	}
-
-	Create(m_hWnd, bMode);
-}
-
-bool CSound::RetSound3D()
-{
-	return m_ctrl3D;
-}
-
-// Indicates whether it is possible to play sounds in 3D.
-
-bool CSound::RetSound3DCap()
-{
-	DSCAPS		dscaps;
-	HRESULT 	hr;
-
-	ZeroMemory( &dscaps, sizeof(DSCAPS) );
-	dscaps.dwSize = sizeof(DSCAPS);
-	hr = m_lpDS->GetCaps(&dscaps);
-	if ( hr != DS_OK )  return false;
-
-	return ( dscaps.dwMaxHw3DAllBuffers > 0 );
-}
-
-
-
-// Returns the state of DirectSound.
-
-bool CSound::RetEnable()
-{
-	return m_bEnable;
-}
-
-
-// Switches on or off the sound.
-
-void CSound::SetState(bool bState)
-{
-	m_bState = bState;
-}
-
-// Specifies the pathname to the CD.
-
-void CSound::SetCDpath(char *path)
-{
-	strcpy(m_CDpath, path);
-}
-
-// Switches on or off the CD-audio music.
-
-void CSound::SetAudioTrack(bool bAudio)
-{
-	m_bAudioTrack = bAudio;
-}
-
-
-// Manages volumes of audio (. Wav) and midi (. Mid).
-
-void CSound::SetAudioVolume(int volume)
-{
-	m_audioVolume = volume;
-}
-
-int CSound::RetAudioVolume()
-{
-	if ( !m_bEnable )  return 0;
-	return m_audioVolume;
-}
-
-void CSound::SetMidiVolume(int volume)
-{
-	m_midiVolume = volume;
-
-	if ( m_bAudioTrack )
-	{
-		InitAudioTrackVolume(m_midiVolume);
-	}
-}
-
-int CSound::RetMidiVolume()
-{
-	if ( !m_bEnable )  return 0;
-	return m_midiVolume;
-}
-
-
-// Reads a file.
-
-bool CSound::ReadFile(Sound sound, char *metaname, char *filename)
-{
-	WaveHeader	wavHdr;
-	DWORD		size;
-	int			err;
-
-	// Open the wave file.
-	err = g_metafile.Open(metaname, filename);
-	if ( err != 0 ) return false;
-
-	// Read in the wave header.
-	g_metafile.Read(&wavHdr, sizeof(wavHdr));
-
-	// Figure out the size of the data region.
-	size = wavHdr.dwDSize;
-
-	if ( m_files[sound] != 0 )
-	{
-		free(m_files[sound]);
-	}
-	m_files[sound] = (char*)malloc(sizeof(WaveHeader)+size);
-
-	memcpy(m_files[sound], &wavHdr, sizeof(WaveHeader));
-	g_metafile.Read(m_files[sound]+sizeof(WaveHeader), size);
-
-	// Close out the wave file.
-	g_metafile.Close();
-	return true;
-}
-
-// Hides all sound files (. Wav).
-
-void CSound::CacheAll()
-{
-	int			i;
-	char		meta[50];
-	char		name[50];
-
-	if ( !m_bEnable )  return;
-
-	if ( m_bDebugMode )
-	{
-		strcpy(meta, "");
-	}
-	else
-	{
-#if _SCHOOL
-		strcpy(meta, "ceebot3.dat");
-#else
-		strcpy(meta, "colobot3.dat");
-#endif
-	}
-
-	for ( i=0 ; i<MAXFILES ; i++ )
-	{
-		if ( m_bDebugMode )
-		{
-			sprintf(name, "sound\\sound%.3d.wav", i);
-		}
-		else
-		{
-			sprintf(name, "sound%.3d.wav", i);
-		}
-		if ( !ReadFile((Sound)i, meta, name) )  break;
-	}
-}
-
-
-// Return the priority of a sound.
-// The higher the value, the greater the sound is important.
-
-int CSound::RetPriority(Sound sound)
-{
-	if ( sound == SOUND_FLYh   ||
-		 sound == SOUND_FLY    ||
-		 sound == SOUND_MOTORw ||
-		 sound == SOUND_MOTORt ||
-		 sound == SOUND_MOTORr ||
-		 sound == SOUND_MOTORs ||
-		 sound == SOUND_SLIDE  ||
-		 sound == SOUND_ERROR  )
-	{
-		return 30;
-	}
-
-	if ( sound == SOUND_CONVERT  ||
-		 sound == SOUND_ENERGY   ||
-		 sound == SOUND_DERRICK  ||
-		 sound == SOUND_STATION  ||
-		 sound == SOUND_REPAIR   ||
-		 sound == SOUND_RESEARCH ||
-		 sound == SOUND_BURN     ||
-		 sound == SOUND_BUILD    ||
-		 sound == SOUND_TREMBLE  ||
-		 sound == SOUND_NUCLEAR  ||
-		 sound == SOUND_EXPLO    ||
-		 sound == SOUND_EXPLOl   ||
-		 sound == SOUND_EXPLOlp  ||
-		 sound == SOUND_EXPLOp   ||
-		 sound == SOUND_EXPLOi   )
-	{
-		return 20;
-	}
-
-	if ( sound == SOUND_BLUP    ||
-		 sound == SOUND_INSECTs ||
-		 sound == SOUND_INSECTa ||
-		 sound == SOUND_INSECTb ||
-		 sound == SOUND_INSECTw ||
-		 sound == SOUND_INSECTm ||
-		 sound == SOUND_PSHHH   ||
-		 sound == SOUND_EGG     )
-	{
-		return 0;
-	}
-
-	return 10;
-}
-
-// Seeks a free buffer.
-
-bool CSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
-{
-	DWORD	status;
-	int		i, priority;
-
-	priority = RetPriority(sound);
-
-#if 1
-	// Seeks a channel used which sound is stopped.
-	for ( i=0 ; i<m_maxSound ; i++ )
-	{
-		if ( !m_channel[i].bUsed )  continue;
-		if ( m_channel[i].type != sound )  continue;
-
-		m_channel[i].soundBuffer->GetStatus(&status);
-		if ( (status&DSBSTATUS_PLAYING) == 0 )
-		{
-			m_channel[i].priority = priority;
-			m_channel[i].uniqueStamp = m_uniqueStamp++;
-			channel = i;
-			bAlreadyLoaded = true;
-			return true;
-		}
-	}
-#endif
-
-	// Seeks a channel completely free.
-	for ( i=0 ; i<m_maxSound ; i++ )
-	{
-		if ( !m_channel[i].bUsed )
-		{
-			m_channel[i].priority = priority;
-			m_channel[i].uniqueStamp = m_uniqueStamp++;
-			channel = i;
-			bAlreadyLoaded = false;
-			return true;
-		}
-	}
-
-	// Seeks a channel used which sound is stopped.
-	for ( i=0 ; i<m_maxSound ; i++ )
-	{
-		if ( !m_channel[i].bUsed )  continue;
-
-		m_channel[i].soundBuffer->GetStatus(&status);
-		if ( (status&DSBSTATUS_PLAYING) == 0 )
-		{
-			m_channel[i].soundBuffer->Release();
-			m_channel[i].soundBuffer = 0;
-			m_channel[i].priority = priority;
-			m_channel[i].uniqueStamp = m_uniqueStamp++;
-
-			channel = i;
-			bAlreadyLoaded = false;
-			return true;
-		}
-	}
-
-	// Seeks a lower priority channel used.
-	for ( i=0 ; i<m_maxSound ; i++ )
-	{
-		if ( !m_channel[i].bUsed )  continue;
-		if ( m_channel[i].priority >= priority )  continue;
-
-		m_channel[i].soundBuffer->Stop();
-		m_channel[i].soundBuffer->Release();
-		m_channel[i].soundBuffer = 0;
-		m_channel[i].priority = priority;
-		m_channel[i].uniqueStamp = m_uniqueStamp++;
-
-		channel = i;
-		bAlreadyLoaded = false;
-		return true;
-	}
-
-	// Seeks a channel used the same or lower priority.
-	for ( i=0 ; i<m_maxSound ; i++ )
-	{
-		if ( !m_channel[i].bUsed )  continue;
-		if ( m_channel[i].priority > priority )  continue;
-
-		m_channel[i].soundBuffer->Stop();
-		m_channel[i].soundBuffer->Release();
-		m_channel[i].soundBuffer = 0;
-		m_channel[i].priority = priority;
-		m_channel[i].uniqueStamp = m_uniqueStamp++;
-
-		channel = i;
-		bAlreadyLoaded = false;
-		return true;
-	}
-
-	char s[100];
-	sprintf(s, "Sound %d forget (priority=%d)\n", sound, priority);
-	OutputDebugString(s);
-
-	return false;
-}
-
-// Reads in data from a wave file.
-
-bool CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size) 
-{
-	LPVOID	pData1;
-	DWORD	dwData1Size;
-	LPVOID	pData2;
-	DWORD	dwData2Size;
-	HRESULT hr;
-
-	// Lock data in buffer for writing.
-	hr = lpDSB->Lock(0, size, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
-	if ( hr != DS_OK )
-	{
-		return false;
-	}
-
-	// Read in first chunk of data.
-	if ( dwData1Size > 0 ) 
-	{
-		memcpy(pData1, m_files[sound]+sizeof(WaveHeader), dwData1Size);
-	}
-
-	// Read in second chunk if necessary.
-	if ( dwData2Size > 0 ) 
-	{
-		memcpy(pData2, m_files[sound]+sizeof(WaveHeader)+dwData1Size, dwData2Size);
-	}
-
-	// Unlock data in buffer.
-	hr = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
-	if ( hr != DS_OK )
-	{
-		return false;
-	}
-
-	return true;
-}
-
-// Creates a DirectSound buffer.
-
-bool CSound::CreateSoundBuffer(int channel, DWORD size, DWORD freq,
-							   DWORD bitsPerSample, DWORD blkAlign,
-							   bool bStereo)
-{
-	PCMWAVEFORMAT	pcmwf;
-	DSBUFFERDESC	dsbdesc;
-	DS3DBUFFER		bufferParams;  // 3D buffer properties
-	HRESULT 		hr;
-	
-	// Set up wave format structure.
-	memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
-	pcmwf.wf.wFormatTag 	 = WAVE_FORMAT_PCM; 	 
-	pcmwf.wf.nChannels		 = bStereo ? 2 : 1;
-	pcmwf.wf.nSamplesPerSec  = freq;
-	pcmwf.wf.nBlockAlign	 = (WORD)blkAlign;
-	pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
-	pcmwf.wBitsPerSample	 = (WORD)bitsPerSample;
-
-	// Set up DSBUFFERDESC structure.
-	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));	// Zero it out. 
-	dsbdesc.dwSize = sizeof(DSBUFFERDESC);
-	if ( m_ctrl3D )
-	{
-		dsbdesc.dwFlags = DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE|
-						  DSBCAPS_LOCDEFER|
-						  DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY;
-	}
-	else
-	{
-		dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY;
-	}
-	dsbdesc.dwBufferBytes = size; 
-	dsbdesc.lpwfxFormat   = (LPWAVEFORMATEX)&pcmwf;
-
-	hr = m_lpDS->CreateSoundBuffer(&dsbdesc, &m_channel[channel].soundBuffer, NULL);
-	if ( hr != DS_OK )  return false;
-
-	if ( m_ctrl3D )
-	{
-		hr = m_channel[channel].soundBuffer->QueryInterface
-							(
-								IID_IDirectSound3DBuffer, 
-								(VOID**)&m_channel[channel].soundBuffer3D
-							);
-		if ( hr != DS_OK )  return false;
-	}
-	
-	m_channel[channel].bUsed = true;
-	m_channel[channel].bMute = false;
-	return true;
-}
-
-// Creates a DirectSound buffer from a wave file.
-
-bool CSound::CreateBuffer(int channel, Sound sound)
-{
-	WaveHeader* wavHdr;
-	DWORD		size;
-	bool		bStereo;
-
-	if ( m_files[sound] == 0 )  return false;
-
-	wavHdr = (WaveHeader*)m_files[sound];
-	size = wavHdr->dwDSize;
-	bStereo = wavHdr->wChnls > 1 ? true : false;
-
-	// Create the sound buffer for the wave file.
-	if ( !CreateSoundBuffer(channel, size, wavHdr->dwSRate,
-							wavHdr->BitsPerSample, wavHdr->wBlkAlign, bStereo) )
-	{
-		return false;
-	}
-
-	// Read the data for the wave file into the sound buffer.
-	if ( !ReadData(m_channel[channel].soundBuffer, sound, size) )
-	{
-		return false;
-	}
-
-	m_channel[channel].type = sound;
-
-	// Close out the wave file.
-	return true;
-}
-
-// Calculates the volume and pan of a sound, non-3D mode.
-
-void CSound::ComputeVolumePan2D(int channel, const Math::Vector &pos)
-{
-	float	dist, a, g;
-
-	if ( pos.x == m_eye.x &&
-		 pos.y == m_eye.y &&
-		 pos.z == m_eye.z )
-	{
-		m_channel[channel].volume = 1.0f;  // maximum volume
-		m_channel[channel].pan    = 0.0f;  // at the center
-		return;
-	}
-
-#if _TEEN
-	dist = Math::Distance(pos, m_eye);
-	if ( dist >= 210.0f )  // very far?
-	{
-		m_channel[channel].volume = 0.0f;  // silence
-		m_channel[channel].pan    = 0.0f;  // at the center
-		return;
-	}
-	if ( dist <= 10.0f )  // very close?
-	{
-		m_channel[channel].volume = 1.0f;  // maximum volume
-		m_channel[channel].pan    = 0.0f;  // at the center
-		return;
-	}
-	m_channel[channel].volume = 1.0f-((dist-10.0f)/200.0f);
-#else
-	dist = Math::Distance(pos, m_eye);
-	if ( dist >= 110.0f )  // very far?
-	{
-		m_channel[channel].volume = 0.0f;  // silence
-		m_channel[channel].pan    = 0.0f;  // at the center
-		return;
-	}
-	if ( dist <= 10.0f )  // very close?
-	{
-		m_channel[channel].volume = 1.0f;  // maximum volume
-		m_channel[channel].pan    = 0.0f;  // at the center
-		return;
-	}
-	m_channel[channel].volume = 1.0f-((dist-10.0f)/100.0f);
-#endif
-
-	a = Math::RotateAngle(m_lookat.x-m_eye.x, m_eye.z-m_lookat.z);
-	g = Math::RotateAngle(pos.x-m_eye.x, m_eye.z-pos.z);
-	m_channel[channel].pan = sinf(Math::Direction(a, g));
-}
-
-// Sounds in the middle.
-// Returns the associated channel or -1.
-
-int CSound::Play(Sound sound, float amplitude, float frequency, bool bLoop)
-{
-	return Play(sound, m_lookat, amplitude, frequency, bLoop);
-}
-
-// Sounds at a given position.
-// Returns the associated channel or -1.
-
-int CSound::Play(Sound sound, Math::Vector pos,
-				 float amplitude, float frequency, bool bLoop)
-{
-	DS3DBUFFER	sb;
-	int			channel, iVolume, iPan, iFreq, uniqueStamp;
-	bool		bAlreadyLoaded;
-	DWORD		flag, freq;
-	HRESULT		err;
-
-	if ( !m_bEnable )  return -1;
-	if ( !m_bState || m_audioVolume == 0 )  return -1;
-
-//?	if ( Math::Distance(pos, m_eye) > 100.0f )  return -1;
-
-	if ( !SearchFreeBuffer(sound, channel, bAlreadyLoaded) )  return -1;
-
-	if ( !bAlreadyLoaded )
-	{
-		if ( !CreateBuffer(channel, sound) )
-		{
-			if ( m_channel[channel].bUsed            &&
-				 m_channel[channel].soundBuffer != 0 )
-			{
-				m_channel[channel].soundBuffer->Release();
-				m_channel[channel].soundBuffer = 0;
-			}
-			m_channel[channel].bUsed = false;
-			return -1;
-		}
-	}
-
-	m_channel[channel].pos = pos;
-
-	if ( m_ctrl3D )
-	{
-		m_channel[channel].volume = 1.0f;
-		m_channel[channel].pan    = 0.0f;
-	}
-	else
-	{
-		ComputeVolumePan2D(channel, pos);
-	}
-
-#if 0
-	DWORD status;
-	m_channel[channel].soundBuffer->GetStatus(&status);
-	char s[100];
-	sprintf(s, "Play sound=%d status=%d channel=%d flag=%d\n", sound, status, channel, bAlreadyLoaded);
-	OutputDebugString(s);
-#endif
-
-	m_channel[channel].oper[0].bUsed = false;
-	m_channel[channel].startAmplitude = amplitude;
-	m_channel[channel].startFrequency = frequency;
-	m_channel[channel].changeFrequency = 1.0f;
-
-	if ( m_ctrl3D )
-	{
-		sb.dwSize = sizeof(DS3DBUFFER);
-		err = m_channel[channel].soundBuffer3D->GetAllParameters(&sb);
-		DisplayError("GetAllParameters", sound, err);
-
-		sb.vPosition = VEC_TO_D3DVEC(pos);
-//?		sb.dwInsideConeAngle = 90;
-//?		sb.dwOutsideConeAngle = 180;
-//?		sb.vConeOrientation = Math::Vector(0.0f, 1.0f, 0.0f);
-		sb.lConeOutsideVolume = DSBVOLUME_MIN;
-#if _TEEN
-		sb.flMinDistance = 50.0f;
-#else
-		sb.flMinDistance = 20.0f;
-#endif
-		sb.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
-
-		err = m_channel[channel].soundBuffer3D->SetAllParameters(&sb, DS3D_IMMEDIATE);
-		DisplayError("SetAllParameters", sound, err);
-	}
-
-	amplitude *= m_channel[channel].volume;
-	amplitude *= (float)m_audioVolume/MAXVOLUME;
-	iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
-	if ( iVolume > 0 )  iVolume = 0;
-	err = m_channel[channel].soundBuffer->SetVolume(iVolume);
-	DisplayError("SetVolume", sound, err);
-
-	if ( !m_ctrl3D )
-	{
-		iPan = (int)(m_channel[channel].pan*10000.0f);
-		err = m_channel[channel].soundBuffer->SetPan(iPan);
-		DisplayError("SetPan", sound, err);
-	}
-
-	if ( !bAlreadyLoaded )
-	{
-		err = m_channel[channel].soundBuffer->GetFrequency(&freq);
-		DisplayError("GetFrequency", sound, err);
-		m_channel[channel].initFrequency = freq;
-	}
-	iFreq = (int)(frequency*m_channel[channel].initFrequency);
-	err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
-	DisplayError("SetFrequency", sound, err);
-
-	err = m_channel[channel].soundBuffer->SetCurrentPosition(0);
-	DisplayError("SetCurrentPosition", sound, err);
-
-	flag = bLoop?DSBPLAY_LOOPING:0;
-//?	flag |= DSBPLAY_LOCHARDWARE|DSBPLAY_TERMINATEBY_DISTANCE;
-//?	flag |= DSBPLAY_TERMINATEBY_DISTANCE;
-	err = m_channel[channel].soundBuffer->Play(0, 0, flag);
-	DisplayError("Play", sound, err);
-	if ( err == DSERR_BADFORMAT )
-	{
-		iFreq = m_channel[channel].initFrequency;
-		err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
-		DisplayError("SetFrequency (repeat)", sound, err);
-
-		err = m_channel[channel].soundBuffer->Play(0, 0, flag);
-		DisplayError("Play (repeat)", sound, err);
-	}
-
-	uniqueStamp = m_channel[channel].uniqueStamp;
-	return channel | ((uniqueStamp&0xffff)<<16);
-}
-
-// Check a channel number.
-// Adapts the channel, so it can be used as an offset in m_channel.
-
-bool CSound::CheckChannel(int &channel)
-{
-	int		uniqueStamp;
-
-	uniqueStamp = (channel>>16)&0xffff;
-	channel &= 0xffff;
-
-	if ( !m_bEnable )  return false;
-	if ( !m_bState || m_audioVolume == 0 )  return false;
-
-	if ( channel < 0 || channel >= m_maxSound )  return false;
-	if ( !m_channel[channel].bUsed )  return false;
-
-	if ( m_channel[channel].uniqueStamp != uniqueStamp )  return false;
-
-	return true;
-}
-
-// Removes all envelopes.
-
-bool CSound::FlushEnvelope(int channel)
-{
-	if ( !CheckChannel(channel) )  return false;
-
-	m_channel[channel].oper[0].bUsed = false;
-	return true;
-}
-
-// Adds an operation envelope.
-
-bool CSound::AddEnvelope(int channel, float amplitude, float frequency,
-						 float time, SoundNext oper)
-{
-	int		i;
-
-	if ( !CheckChannel(channel) )  return false;
-
-	for ( i=0 ; i<MAXOPER ; i++ )
-	{
-		if ( m_channel[channel].oper[i].bUsed )  continue;
-
-		m_channel[channel].oper[i].bUsed = true;
-		m_channel[channel].oper[i].finalAmplitude = amplitude;
-		m_channel[channel].oper[i].finalFrequency = frequency;
-		m_channel[channel].oper[i].totalTime = time;
-		m_channel[channel].oper[i].currentTime = 0;
-		m_channel[channel].oper[i].nextOper = oper;
-
-		if ( i < MAXOPER-1 )
-		{
-			m_channel[channel].oper[i+1].bUsed = false;
-		}
-		return true;
-	}
-	return false;
-}
-
-// Changes the position of a sound.
-
-bool CSound::Position(int channel, Math::Vector pos)
-{
-	float		amplitude, pan;
-	int			iVolume, iPan;
-	HRESULT		err;
-
-	if ( !CheckChannel(channel) )  return false;
-
-	m_channel[channel].pos = pos;
-
-	if ( m_ctrl3D )
-	{
-		m_channel[channel].soundBuffer3D->SetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED);
-	}
-	else
-	{
-		ComputeVolumePan2D(channel, pos);
-
-		if ( !m_channel[channel].oper[0].bUsed )
-		{
-			amplitude = m_channel[channel].startAmplitude;
-			amplitude *= m_channel[channel].volume;
-			amplitude *= (float)m_audioVolume/MAXVOLUME;
-			iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
-			if ( iVolume > 0 )  iVolume = 0;
-			err = m_channel[channel].soundBuffer->SetVolume(iVolume);
-			DisplayError("SetVolume", m_channel[channel].type, err);
-		}
-
-		pan = m_channel[channel].pan;
-		iPan = (int)(pan*10000.0f);
-		err = m_channel[channel].soundBuffer->SetPan(iPan);
-		DisplayError("SetPan", m_channel[channel].type, err);
-	}
-	return true;
-}
-
-// Changes the frequency of a sound.
-// 0.5 down of an octave and 2.0 up of an octave.
-
-bool CSound::Frequency(int channel, float frequency)
-{
-	HRESULT	err;
-	int		iFreq;
-
-	if ( !CheckChannel(channel) )  return false;
-
-	m_channel[channel].changeFrequency = frequency;
-
-	if ( !m_channel[channel].oper[0].bUsed )
-	{
-		iFreq = (int)(frequency*m_channel[channel].initFrequency);
-		err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
-		DisplayError("Frequency", m_channel[channel].type, err);
-	}
-
-	return true;
-}
-
-// Stops sound.
-
-bool CSound::Stop(int channel)
-{
-	if ( !CheckChannel(channel) )  return false;
-
-	m_channel[channel].soundBuffer->Stop();
-	return true;
-}
-
-// Stops all sounds.
-
-bool CSound::StopAll()
-{
-	DWORD	status;
-	int 	i;
-
-	for ( i=0 ; i<MAXSOUND ; i++ )
-	{
-		if ( !m_channel[i].bUsed )  continue;
-
-		m_channel[i].soundBuffer->GetStatus(&status);
-		if ( (status&DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING )
-		{
-			m_channel[i].soundBuffer->Stop();
-		}
-		m_channel[i].soundBuffer->Stop();
-		m_channel[i].soundBuffer->Release();
-		m_channel[i].soundBuffer = 0;
-
-		m_channel[i].bUsed = false;
-	}
-	return true;
-}
-
-// Silent all sounds.
-
-bool CSound::MuteAll(bool bMute)
-{
-	int 	i;
-
-	for ( i=0 ; i<MAXSOUND ; i++ )
-	{
-		if ( !m_channel[i].bUsed )  continue;
-
-		m_channel[i].bMute = bMute;
-	}
-	return true;
-}
-
-
-// Passes the following operation for a channel.
-
-void CSound::OperNext(int channel)
-{
-	int		i;
-
-	m_channel[channel].startAmplitude = m_channel[channel].oper[0].finalAmplitude;
-	m_channel[channel].startFrequency = m_channel[channel].oper[0].finalFrequency;
-
-	for ( i=0 ; i<MAXOPER-1 ; i++ )
-	{
-		if ( !m_channel[channel].oper[i+1].bUsed )  break;
-
-		m_channel[channel].oper[i] = m_channel[channel].oper[i+1];
-	}
-
-	m_channel[channel].oper[i].bUsed = false;
-}
-
-// Updates the sound buffers.
-
-void CSound::FrameMove(float rTime)
-{
-	HRESULT		err;
-	SoundNext	next;
-	float		progress, volume, freq;
-	int			i, iVolume, iFreq;
-
-	m_playTime += rTime;
-
-	for ( i=0 ; i<m_maxSound ; i++ )
-	{
-		if ( !m_channel[i].bUsed )  continue;
-		if ( !m_channel[i].oper[0].bUsed )  continue;
-
-		if ( m_channel[i].bMute )
-		{
-			m_channel[i].soundBuffer->SetVolume(-10000);  // silence
-			continue;
-		}
-
-		m_channel[i].oper[0].currentTime += rTime;
-
-		progress = m_channel[i].oper[0].currentTime / m_channel[i].oper[0].totalTime;
-		if ( progress > 1.0f )  progress = 1.0f;
-
-		volume = progress;
-		volume *= m_channel[i].oper[0].finalAmplitude-m_channel[i].startAmplitude;
-		volume += m_channel[i].startAmplitude;
-		volume *= m_channel[i].volume;
-		volume *= (float)m_audioVolume/MAXVOLUME;
-		iVolume = (int)((powf(volume, 0.2f)-1.0f)*10000.0f);
-		if ( iVolume > 0 )  iVolume = 0;
-		m_channel[i].soundBuffer->SetVolume(iVolume);
-
-		freq = progress;
-		freq *= m_channel[i].oper[0].finalFrequency-m_channel[i].startFrequency;
-		freq += m_channel[i].startFrequency;
-		freq *= m_channel[i].changeFrequency;
-		iFreq = (int)(freq*m_channel[i].initFrequency);
-		err = m_channel[i].soundBuffer->SetFrequency(iFreq);
-		DisplayError("FrameMove::Frequency", m_channel[i].type, err);
-
-		if ( m_channel[i].oper[0].currentTime >=
-			 m_channel[i].oper[0].totalTime )
-		{
-			next = m_channel[i].oper[0].nextOper;
-
-			if ( next == SOPER_LOOP )
-			{
-				m_channel[i].oper[0].currentTime = 0.0f;
-			}
-			else
-			{
-				OperNext(i);
-
-				if ( next == SOPER_STOP )
-				{
-					m_channel[i].soundBuffer->Stop();
-				}
-			}
-		}
-	}
-
-	m_lastTime += rTime;
-	if ( m_lastTime >= 0.05f && m_listener != 0 )
-	{
-		m_lastTime = 0.0f;
-		m_listener->CommitDeferredSettings();
-	}
-}
-
-// Specifies the position of the listener.
-// Must be called whenever the camera moves.
-
-void CSound::SetListener(Math::Vector eye, Math::Vector lookat)
-{
-	DS3DLISTENER	listenerParams;
-	HRESULT			err;
-	float			amplitude, pan;
-	int				i, iVolume, iPan;
-
-	m_eye = eye;
-	m_lookat = lookat;
-
-	if ( m_listener == 0 )
-	{
-		if ( m_ctrl3D )  return;
-
-		for ( i=0 ; i<m_maxSound ; i++ )
-		{
-			if ( !m_channel[i].bUsed )  continue;
-
-			ComputeVolumePan2D(i, m_channel[i].pos);
-
-			if ( !m_channel[i].oper[0].bUsed )
-			{
-				amplitude = m_channel[i].startAmplitude;
-				amplitude *= m_channel[i].volume;
-				amplitude *= (float)m_audioVolume/MAXVOLUME;
-				iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
-				if ( iVolume > 0 )  iVolume = 0;
-				err = m_channel[i].soundBuffer->SetVolume(iVolume);
-				DisplayError("SetVolume", m_channel[i].type, err);
-			}
-
-			pan = m_channel[i].pan;
-			iPan = (int)(pan*10000.0f);
-			err = m_channel[i].soundBuffer->SetPan(iPan);
-			DisplayError("SetPan", m_channel[i].type, err);
-		}
-		return;
-	}
-
-	// Get listener parameters.
-	listenerParams.dwSize = sizeof(DS3DLISTENER);
-	m_listener->GetAllParameters(&listenerParams);
-
-	listenerParams.vPosition = VEC_TO_D3DVEC(eye);
-	listenerParams.vOrientFront = VEC_TO_D3DVEC(lookat-eye);
-	listenerParams.vOrientTop = D3DVECTOR(0.0f, 1.0f, 0.0f);
-	listenerParams.flDistanceFactor = 10.0f;
-	listenerParams.flRolloffFactor = 1.0f;
-
-	m_listener->SetAllParameters(&listenerParams, DS3D_DEFERRED);
-}
-
-
-
-
-// Uses MCI to play a MIDI file. The window procedure
-// is notified when playback is complete.
-
-bool CSound::PlayMusic(int rank, bool bRepeat)
-{
-	MCI_OPEN_PARMS	mciOpenParms;
-	MCI_PLAY_PARMS	mciPlayParms;
-	DWORD			dwReturn;
-	char			filename[MAX_PATH];
-
-	m_bRepeatMusic = bRepeat;
-	m_playTime = 0.0f;
-
-	if ( m_midiVolume == 0 )  return true;
-
-	if ( m_bAudioTrack )
-	{
-		return PlayAudioTrack(rank);
-	}
-
-	if ( !m_bEnable )  return true;
-	InitMidiVolume(m_midiVolume);
-	m_lastMidiVolume = m_midiVolume;
-
-	GetCurrentDir(filename, MAX_PATH-30);
-	sprintf(filename+strlen(filename), "sound\\music%.3d.blp", rank-1);
-
-	// Open the device by specifying the device and filename.
-	// MCI will attempt to choose the MIDI mapper as the output port.
-	mciOpenParms.lpstrDeviceType = "sequencer";
-	mciOpenParms.lpstrElementName = filename;
-	dwReturn = mciSendCommand(NULL,
-							  MCI_OPEN,
-							  MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,
-							  (DWORD)(LPVOID)&mciOpenParms);
-	if ( dwReturn != 0 )
-	{
-		mciGetErrorString(dwReturn, filename, 128);
-		// Failed to open device. Don't close it; just return error.
-		return false;
-	}
-
-	// The device opened successfully; get the device ID.
-	m_MidiDeviceID = mciOpenParms.wDeviceID;
-
-	// Begin playback. 
-	mciPlayParms.dwCallback = (DWORD)m_hWnd;
-	dwReturn = mciSendCommand(m_MidiDeviceID,
-							  MCI_PLAY,
-							  MCI_NOTIFY, 
-							  (DWORD)(LPVOID)&mciPlayParms);
-	if ( dwReturn != 0 )
-	{
-		mciGetErrorString(dwReturn, filename, 128);
-		StopMusic();
-		return false;
-	}
-
-	m_MIDIMusic = rank;
-	return true;
-}
-
-// Uses MCI to play a CD-audio track. The window procedure
-// is notified when playback is complete.
-// The rank parameter is in space [1..n] !
-// For CD mix (data/audio), it will be [2..n] !
-
-bool CSound::PlayAudioTrack(int rank)
-{
-#if _SOUNDTRACKS
-	MCI_OPEN_PARMS	mciOpenParms;
-	MCI_PLAY_PARMS	mciPlayParms;
-	MCI_SET_PARMS	mciSetParms;
-	DWORD			dwReturn;
-	char			filename[MAX_PATH];
-	char			device[10];
-
-	if ( !m_bEnable )  return true;
-//?	if ( m_midiVolume == 0 )  return true;
-	InitAudioTrackVolume(m_midiVolume);
-	m_lastMidiVolume = m_midiVolume;
-
-	// Open the device by specifying the device and filename.
-	// MCI will attempt to choose the MIDI mapper as the output port.
-	memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
-//?	mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
-//?	dwReturn = mciSendCommand(NULL,
-//?							  MCI_OPEN,
-//?							  MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
-//?							  (DWORD)(LPVOID)&mciOpenParms);
-	mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
-	if ( m_CDpath[0] == 0 )
-	{
-		dwReturn = mciSendCommand(NULL,
-								  MCI_OPEN,
-								  MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
-								  (DWORD)(LPVOID)&mciOpenParms);
-	}
-	else
-	{
-		device[0] = m_CDpath[0];
-		device[1] = ':';
-		device[2] = 0;
-		mciOpenParms.lpstrElementName = device;
-		dwReturn = mciSendCommand(NULL,
-								  MCI_OPEN,
-								  MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
-								  (DWORD)(LPVOID)&mciOpenParms);
-	}
-	if ( dwReturn != 0 )
-	{
-		mciGetErrorString(dwReturn, filename, 128);
-		// Failed to open device. Don't close it; just return error.
-		return false;
-	}
-
-	// The device opened successfully; get the device ID.
-	m_MidiDeviceID = mciOpenParms.wDeviceID;
-
-	// Set the time format to track/minute/second/frame (TMSF).
-	memset(&mciSetParms, 0, sizeof(MCI_SET_PARMS));
-	mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
-	dwReturn = mciSendCommand(m_MidiDeviceID,
-							  MCI_SET,
-							  MCI_SET_TIME_FORMAT,
-							  (DWORD)&mciSetParms);
-	if ( dwReturn != 0 )
-	{
-		mciGetErrorString(dwReturn, filename, 128);
-		StopMusic();
-		return false;
-	}  
-
-	// Begin playback.
-	memset(&mciPlayParms, 0, sizeof(MCI_PLAY_PARMS));
-	mciPlayParms.dwCallback = (DWORD)m_hWnd;
-	mciPlayParms.dwFrom = MCI_MAKE_TMSF(rank+0, 0, 0, 0);
-	mciPlayParms.dwTo   = MCI_MAKE_TMSF(rank+1, 0, 0, 0);
-	dwReturn = mciSendCommand(m_MidiDeviceID,
-							  MCI_PLAY,
-							  MCI_NOTIFY|MCI_FROM|MCI_TO,
-							  (DWORD)(LPVOID)&mciPlayParms);
-	if ( dwReturn != 0 )
-	{
-		mciGetErrorString(dwReturn, filename, 128);
-		StopMusic();
-		return false;
-	}
-
-	m_MIDIMusic = rank;
-#endif
-	return true;
-}
-
-// Restart the MIDI player.
-
-bool CSound::RestartMusic()
-{
-	if ( !m_bRepeatMusic )  return false;
-
-	OutputDebugString("RestartMusic\n");
-	if ( !m_bEnable )  return true;
-//?	if ( m_midiVolume == 0 )  return true;
-	if ( m_MIDIMusic == 0 )  return false;
-	if ( m_playTime < 5.0f )  return false;
-
-	return PlayMusic(m_MIDIMusic, true);
-}
-
-// Shuts down the MIDI player.
-
-void CSound::SuspendMusic()
-{
-	if ( !m_bEnable )  return;
-
-//?	if ( m_MidiDeviceID && m_midiVolume != 0 )
-	if ( m_MidiDeviceID )
-	{
-		if ( m_bAudioTrack )  mciSendCommand(m_MidiDeviceID, MCI_STOP, 0, NULL);
-		mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL);
-	}
-	m_MidiDeviceID = 0;
-}
-
-// Shuts down the MIDI player.
-
-void CSound::StopMusic()
-{
-	SuspendMusic();
-	m_MIDIMusic = 0;
-}
-
-// Returns true if the music is in progress.
-
-bool CSound::IsPlayingMusic()
-{
-	return (m_MIDIMusic != 0);
-}
-
-// Adjusts the volume of currently music, if necessary.
-
-void CSound::AdaptVolumeMusic()
-{
-	if ( m_midiVolume != m_lastMidiVolume )
-	{
-		if ( m_bAudioTrack )
-		{
-			InitAudioTrackVolume(m_midiVolume);
-		}
-		else
-		{
-			InitMidiVolume(m_midiVolume);
-		}
-		m_lastMidiVolume = m_midiVolume;
-		RestartMusic();
-	}
-}
-
diff --git a/src/sound/sound.h b/src/sound/sound.h
index 2dcdc2cf..be635585 100644
--- a/src/sound/sound.h
+++ b/src/sound/sound.h
@@ -1,242 +1,165 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see  http://www.gnu.org/licenses/.
-
-// sound.h
-
-#pragma once
-
-
-#include <dsound.h>
-
-
-const int MAXFILES	= 200;
-const int MAXSOUND	= 32;
-const int MAXVOLUME	= 20;
-const int MAXOPER	= 4;
-
-class CInstanceManager;
-
-
-enum Sound
-{
-	SOUND_CLICK		= 0,
-	SOUND_BOUM		= 1,
-	SOUND_EXPLO		= 2,
-	SOUND_FLYh		= 3,	// human
-	SOUND_FLY		= 4,
-	SOUND_STEPs		= 5,	// smooth
-	SOUND_MOTORw		= 6,	// wheel
-	SOUND_MOTORt		= 7,	// tank
-	SOUND_MOTORr		= 8,	// roller
-	SOUND_ERROR		= 9,
-	SOUND_CONVERT		= 10,
-	SOUND_ENERGY		= 11,
-	SOUND_PLOUF		= 12,
-	SOUND_BLUP		= 13,
-	SOUND_WARNING		= 14,
-	SOUND_DERRICK		= 15,
-	SOUND_LABO		= 16,
-	SOUND_STATION		= 17,
-	SOUND_REPAIR		= 18,
-	SOUND_RESEARCH		= 19,
-	SOUND_INSECTs		= 20,	// spider
-	SOUND_BURN		= 21,
-	SOUND_TZOING		= 22,
-	SOUND_GGG		= 23,
-	SOUND_MANIP		= 24,
-	SOUND_FIRE		= 25,	// shooting with fireball
-	SOUND_HUMAN1		= 26,	// breathing
-	SOUND_STEPw		= 27,	// water
-	SOUND_SWIM		= 28,
-	SOUND_RADAR		= 29,
-	SOUND_BUILD		= 30,
-	SOUND_ALARM		= 31,	// energy alarm
-	SOUND_SLIDE		= 32,
-	SOUND_EXPLOi		= 33,	// insect
-	SOUND_INSECTa		= 34,	// ant
-	SOUND_INSECTb		= 35,	// bee
-	SOUND_INSECTw		= 36,	// worm
-	SOUND_INSECTm		= 37,	// mother
-	SOUND_TREMBLE		= 38,
-	SOUND_PSHHH		= 39,
-	SOUND_NUCLEAR		= 40,
-	SOUND_INFO		= 41,
-	SOUND_OPEN		= 42,
-	SOUND_CLOSE		= 43,
-	SOUND_FACTORY		= 44,
-	SOUND_EGG		= 45,
-	SOUND_MOTORs		= 46,	// submarine
-	SOUND_MOTORi		= 47,	// insect (legs)
-	SOUND_SHIELD		= 48,
-	SOUND_FIREi		= 49,	// shooting with orgaball (insect)
-	SOUND_GUNDEL		= 50,
-	SOUND_PSHHH2		= 51,	// shield
-	SOUND_MESSAGE		= 52,
-	SOUND_BOUMm		= 53,	// metal
-	SOUND_BOUMv		= 54,	// plant
-	SOUND_BOUMs		= 55,	// smooth
-	SOUND_EXPLOl		= 56,	// little
-	SOUND_EXPLOlp		= 57,	// little power
-	SOUND_EXPLOp		= 58,	// power
-	SOUND_STEPh		= 59,	// hard
-	SOUND_STEPm		= 60,	// metal
-	SOUND_POWERON		= 61,
-	SOUND_POWEROFF		= 62,
-	SOUND_AIE		= 63,
-	SOUND_WAYPOINT		= 64,
-	SOUND_RECOVER		= 65,
-	SOUND_DEADi		= 66,
-	SOUND_JOSTLE		= 67,
-	SOUND_GFLAT		= 68,
-	SOUND_DEADg		= 69,	// shooting death
-	SOUND_DEADw		= 70,	// drowning
-	SOUND_FLYf		= 71,	// reactor fail
-	SOUND_ALARMt		= 72,	// temperature alarm
-	SOUND_FINDING		= 73,	// finds a cache object
-	SOUND_THUMP		= 74,
-	SOUND_TOUCH		= 75,
-	SOUND_BLITZ		= 76,
-	SOUND_MUSHROOM		= 77,
-	SOUND_FIREp		= 78,	// shooting with phazer
-	SOUND_EXPLOg1		= 79,	// impact gun 1
-	SOUND_EXPLOg2		= 80,	// impact gun 2
-	SOUND_MOTORd		= 81,	// engine friction
-};
-
-enum SoundNext
-{
-	SOPER_CONTINUE	= 1,
-	SOPER_STOP		= 2,
-	SOPER_LOOP		= 3,
-};
-
-struct SoundOper
-{
-	char		bUsed;
-	float		finalAmplitude;
-	float		finalFrequency;
-	float		totalTime;
-	float		currentTime;
-	SoundNext	nextOper;
-};
-
-struct SoundChannel
-{
-	char					bUsed;			// buffer used?
-	char					bMute;			// silence?
-	Sound					type;			// SOUND_*
-	int					priority;		// so great -> important
-	Math::Vector				pos;			// position in space
-	unsigned short				uniqueStamp;		// unique marker
-	LPDIRECTSOUNDBUFFER			soundBuffer;
-	LPDIRECTSOUND3DBUFFER			soundBuffer3D;
-	float					startAmplitude;
-	float					startFrequency;
-	float					changeFrequency;
-	int					initFrequency;
-	float					volume;			// 2D: volume 1..0 depending on position
-	float					pan;			// 2D: pan -1..+1 depending on position
-	SoundOper				oper[MAXOPER];
-};
-
-
-
-class CSound
-{
-public:
-	CSound(CInstanceManager* iMan);
-	~CSound();
-
-	void	SetDebugMode(bool bMode);
-	bool	Create(HWND hWnd, bool b3D);
-	void	CacheAll();
-
-	void	SetState(bool bState);
-	bool	RetEnable();
-
-	void	SetCDpath(char *path);
-	void	SetAudioTrack(bool bAudio);
-
-	void	SetSound3D(bool bMode);
-	bool	RetSound3D();
-	bool	RetSound3DCap();
-
-	void	SetAudioVolume(int volume);
-	int		RetAudioVolume();
-	void	SetMidiVolume(int volume);
-	int		RetMidiVolume();
-
-	void	SetListener(Math::Vector eye, Math::Vector lookat);
-	void	FrameMove(float rTime);
-
-	int		Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
-	int		Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
-	bool	FlushEnvelope(int channel);
-	bool	AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
-	bool	Position(int channel, Math::Vector pos);
-	bool	Frequency(int channel, float frequency);
-	bool	Stop(int channel);
-	bool	StopAll();
-	bool	MuteAll(bool bMute);
-
-	bool	PlayMusic(int rank, bool bRepeat);
-	bool	RestartMusic();
-	void	SuspendMusic();
-	void	StopMusic();
-	bool	IsPlayingMusic();
-	void	AdaptVolumeMusic();
-
-protected:
-	bool	CheckChannel(int &channel);
-	bool	CreateSoundBuffer(int channel, DWORD size, DWORD freq, DWORD bitsPerSample, DWORD blkAlign, bool bStereo);
-	bool	ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size);
-	bool	CreateBuffer(int channel, Sound sound);
-	void	ComputeVolumePan2D(int channel, const Math::Vector &pos);
-	bool	ReadFile(Sound sound, char *metaname, char *filename);
-	int		RetPriority(Sound sound);
-	bool	SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
-	void	OperNext(int channel);
-	bool	PlayAudioTrack(int rank);
-
-protected:
-	CInstanceManager*		m_iMan;
-
-	HWND					m_hWnd;
-	bool					m_bEnable;
-	bool					m_bState;
-	bool					m_bAudioTrack;
-	bool					m_ctrl3D;
-	bool					m_bDebugMode;
-	LPDIRECTSOUND			m_lpDS;
-	LPDIRECTSOUND3DLISTENER	m_listener;
-	SoundChannel			m_channel[MAXSOUND];
-	char*					m_files[MAXFILES];
-	UINT					m_MidiDeviceID;
-	int						m_MIDIMusic;
-	bool					m_bRepeatMusic;
-	int						m_audioVolume;
-	int						m_midiVolume;
-	int						m_lastMidiVolume;
-	Math::Vector				m_eye;
-	Math::Vector				m_lookat;
-	float					m_lastTime;
-	float					m_playTime;
-	int						m_uniqueStamp;
-	int						m_maxSound;
-	char					m_CDpath[100];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see  http://www.gnu.org/licenses/.
+
+// sound.h
+
+#pragma once
+
+
+#include "math/vector.h"
+
+
+class CInstanceManager;
+
+namespace Snd {
+
+const int MAXFILES	= 200;
+const int MAXSOUND	= 32;
+const int MAXVOLUME	= 20;
+const int MAXOPER	= 4;
+
+
+enum Sound
+{
+	SOUND_CLICK		= 0,
+	SOUND_BOUM		= 1,
+	SOUND_EXPLO		= 2,
+	SOUND_FLYh		= 3,	// human
+	SOUND_FLY		= 4,
+	SOUND_STEPs		= 5,	// smooth
+	SOUND_MOTORw		= 6,	// wheel
+	SOUND_MOTORt		= 7,	// tank
+	SOUND_MOTORr		= 8,	// roller
+	SOUND_ERROR		= 9,
+	SOUND_CONVERT		= 10,
+	SOUND_ENERGY		= 11,
+	SOUND_PLOUF		= 12,
+	SOUND_BLUP		= 13,
+	SOUND_WARNING		= 14,
+	SOUND_DERRICK		= 15,
+	SOUND_LABO		= 16,
+	SOUND_STATION		= 17,
+	SOUND_REPAIR		= 18,
+	SOUND_RESEARCH		= 19,
+	SOUND_INSECTs		= 20,	// spider
+	SOUND_BURN		= 21,
+	SOUND_TZOING		= 22,
+	SOUND_GGG		= 23,
+	SOUND_MANIP		= 24,
+	SOUND_FIRE		= 25,	// shooting with fireball
+	SOUND_HUMAN1		= 26,	// breathing
+	SOUND_STEPw		= 27,	// water
+	SOUND_SWIM		= 28,
+	SOUND_RADAR		= 29,
+	SOUND_BUILD		= 30,
+	SOUND_ALARM		= 31,	// energy alarm
+	SOUND_SLIDE		= 32,
+	SOUND_EXPLOi		= 33,	// insect
+	SOUND_INSECTa		= 34,	// ant
+	SOUND_INSECTb		= 35,	// bee
+	SOUND_INSECTw		= 36,	// worm
+	SOUND_INSECTm		= 37,	// mother
+	SOUND_TREMBLE		= 38,
+	SOUND_PSHHH		= 39,
+	SOUND_NUCLEAR		= 40,
+	SOUND_INFO		= 41,
+	SOUND_OPEN		= 42,
+	SOUND_CLOSE		= 43,
+	SOUND_FACTORY		= 44,
+	SOUND_EGG		= 45,
+	SOUND_MOTORs		= 46,	// submarine
+	SOUND_MOTORi		= 47,	// insect (legs)
+	SOUND_SHIELD		= 48,
+	SOUND_FIREi		= 49,	// shooting with orgaball (insect)
+	SOUND_GUNDEL		= 50,
+	SOUND_PSHHH2		= 51,	// shield
+	SOUND_MESSAGE		= 52,
+	SOUND_BOUMm		= 53,	// metal
+	SOUND_BOUMv		= 54,	// plant
+	SOUND_BOUMs		= 55,	// smooth
+	SOUND_EXPLOl		= 56,	// little
+	SOUND_EXPLOlp		= 57,	// little power
+	SOUND_EXPLOp		= 58,	// power
+	SOUND_STEPh		= 59,	// hard
+	SOUND_STEPm		= 60,	// metal
+	SOUND_POWERON		= 61,
+	SOUND_POWEROFF		= 62,
+	SOUND_AIE		= 63,
+	SOUND_WAYPOINT		= 64,
+	SOUND_RECOVER		= 65,
+	SOUND_DEADi		= 66,
+	SOUND_JOSTLE		= 67,
+	SOUND_GFLAT		= 68,
+	SOUND_DEADg		= 69,	// shooting death
+	SOUND_DEADw		= 70,	// drowning
+	SOUND_FLYf		= 71,	// reactor fail
+	SOUND_ALARMt		= 72,	// temperature alarm
+	SOUND_FINDING		= 73,	// finds a cache object
+	SOUND_THUMP		= 74,
+	SOUND_TOUCH		= 75,
+	SOUND_BLITZ		= 76,
+	SOUND_MUSHROOM		= 77,
+	SOUND_FIREp		= 78,	// shooting with phazer
+	SOUND_EXPLOg1		= 79,	// impact gun 1
+	SOUND_EXPLOg2		= 80,	// impact gun 2
+	SOUND_MOTORd		= 81,	// engine friction
+};
+
+enum SoundNext
+{
+	SOPER_CONTINUE	= 1,
+	SOPER_STOP		= 2,
+	SOPER_LOOP		= 3,
+};
+
+struct SoundOper
+{
+	char		bUsed;
+	float		finalAmplitude;
+	float		finalFrequency;
+	float		totalTime;
+	float		currentTime;
+	Snd::SoundNext	nextOper;
+};
+
+struct SoundChannel
+{
+	char					bUsed;			// buffer used?
+	char					bMute;			// silence?
+	Snd::Sound					type;			// SOUND_*
+	int					priority;		// so great -> important
+	Math::Vector				pos;			// position in space
+	unsigned short				uniqueStamp;		// unique marker
+//	LPDIRECTSOUNDBUFFER			soundBuffer;
+//	LPDIRECTSOUND3DBUFFER			soundBuffer3D;
+	float					startAmplitude;
+	float					startFrequency;
+	float					changeFrequency;
+	int					initFrequency;
+	float					volume;			// 2D: volume 1..0 depending on position
+	float					pan;			// 2D: pan -1..+1 depending on position
+	Snd::SoundOper				oper[MAXOPER];
+};
+
+
+
+class CSound
+{
+	// TODO
+};
+
+}; // namespace Sound
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index 330eaccc..525cab26 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -31,7 +31,7 @@
 #include "common/misc.h"
 #include "common/iman.h"
 #include "old/text.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "ui/control.h"
 
 
diff --git a/src/ui/displaytext.cpp b/src/ui/displaytext.cpp
index df08c247..b21d96e3 100644
--- a/src/ui/displaytext.cpp
+++ b/src/ui/displaytext.cpp
@@ -36,7 +36,7 @@
 #include "ui/window.h"
 #include "ui/group.h"
 #include "old/text.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "ui/displaytext.h"
 
 
diff --git a/src/ui/key.cpp b/src/ui/key.cpp
index a581674f..941dd8a4 100644
--- a/src/ui/key.cpp
+++ b/src/ui/key.cpp
@@ -28,7 +28,7 @@
 #include "common/misc.h"
 #include "common/iman.h"
 #include "common/restext.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "old/text.h"
 #include "ui/key.h"
 
diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp
index bc9f5b4c..267c4b1d 100644
--- a/src/ui/maindialog.cpp
+++ b/src/ui/maindialog.cpp
@@ -52,7 +52,7 @@
 #include "ui/editvalue.h"
 #include "old/text.h"
 #include "old/camera.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "script/cmdtoken.h"
 #include "object/robotmain.h"
 #include "ui/maindialog.h"
diff --git a/src/ui/studio.cpp b/src/ui/studio.cpp
index b9f8d957..d37c6fdf 100644
--- a/src/ui/studio.cpp
+++ b/src/ui/studio.cpp
@@ -38,7 +38,7 @@
 #include "object/robotmain.h"
 #include "object/object.h"
 #include "old/camera.h"
-#include "sound/sound.h"
+#include "old/sound.h"
 #include "script/script.h"
 #include "ui/interface.h"
 #include "ui/button.h"